[Flutter 심화] 6. Sliver (4)

김주희's avatar
Aug 05, 2025
[Flutter 심화] 6. Sliver (4)
flexibleSpace 쓰려면 expandedHeight 필수
 
SliverPersistentHeader는 delegate,floating,pinned 속성 가짐
 
? 상속받아야됨
 
SliverPersistentHeaderDelegate 상속받는 MyHeader 클래스 생성
 
CustomScrollView가 호출해서 높이 계산할때 쓰는 getter maxExtent, minExtent
 
pinned=true때문에 올리면 걸린다.
min은 올렸을때 걸리면서 줄어드는 사이즈
notion image
notion image

SliverFillViewport
Viewport - 화면을 꽉채움
notion image
notion image

그림을 그리는데 스크롤이 없을 수도 있음
그럼 컬럼 쓰면 됨 → 남은 공간 Expanded로 채우면 됨
ListView에서는 불가능
Sliver에서는 남은 공간 채우기 가능함
SliverFillRemaining
  1. 남은 공간 차지
  1. 꽉 채우기(스크롤?)
남은 공간 다 잡는데 스크롤하면 스크롤 가능해짐
근데 쓸일 잘 없음 별로 안중요함
 
NestedScrollView를 안쓰면 쓸일이 있긴 함
 
SliverList, SliverPersistentHeader,SliverFillViewport 이런게 중요하지
notion image
notion image
notion image

SliverGrid 이런건 걍 알아서 해보면 됨
 
 
import 'package:flutter/material.dart'; // SliverAppbar + SliverList void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( title: Text("Sliver2"), pinned: false, floating: true, snap: true, expandedHeight: 250, flexibleSpace: Container( color: Colors.yellow, ), ), SliverPersistentHeader(delegate: MyHeader(), pinned: true), SliverList( delegate: SliverChildBuilderDelegate( childCount: 30, (context, index) { return Container( height: 50, color: Colors.lightBlue[100 * (index % 9)], ); }, ), ), SliverFillViewport( delegate: SliverChildBuilderDelegate( childCount: 5, (context, index) { return Container( color: Colors.green[100 * (index % 9)], ); }, ), ), SliverToBoxAdapter( child: Container( color: Colors.red, height: 100, ), ), ], ), ); } } class MyHeader extends SliverPersistentHeaderDelegate { /// 이 위젯은 헤더가 보이는 Sliver 콘텐츠의 일부일 때 빌드됩니다. /// `shrinkOffset`: 0.0부터 `maxExtent` 사이의 값으로, 헤더가 화면 밖으로 얼마나 스크롤되었는지 나타냅니다. /// `overlapsContent`: 헤더가 다른 콘텐츠(예: 플로팅 앱바)와 겹쳐 있으면 true입니다. @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( color: Colors.white, height: 200, // maxExtent와 동일해야한다. child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [Text("Persistence Header"), Icon(Icons.access_time_filled_rounded)], ), ); } /// 헤더가 가질 수 있는 최대 높이입니다. 일반적으로 헤더가 완전히 확장되었을 때의 높이입니다. @override double get maxExtent => 200; /// 헤더가 가질 수 있는 최소 높이입니다. 일반적으로 헤더가 완전히 축소되었을 때의 높이입니다. @override double get minExtent => 100; /// 헤더를 다시 빌드해야 하는지 결정합니다. /// 구성이 변경되었을 때만 다시 빌드하는 것이 좋습니다. /// 이 구현에서는 이전 delegate가 같은 타입이 아니거나 최대/최소 높이가 변경되었을 때 다시 빌드합니다. @override bool shouldRebuild(covariant MyHeader oldDelegate) { return false; } }
import 'package:flutter/material.dart'; // SliverAppbar + SliverList void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( title: Text("Sliver2"), pinned: false, floating: true, snap: true, expandedHeight: 250, flexibleSpace: Container( color: Colors.yellow, ), ), SliverToBoxAdapter( child: Container( color: Colors.red, height: 100, ), ), SliverFillRemaining( child: Container( color: Colors.blue, ), ), ], ), ); } }
Share article

jay0628