![[Flutter 심화] 6. Sliver (4)](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BFlutter%2520%25EC%258B%25AC%25ED%2599%2594%255D%25206.%2520Sliver%2520%284%29%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3Djay0628&w=2048&q=75)
flexibleSpace 쓰려면 expandedHeight 필수
SliverPersistentHeader는 delegate,floating,pinned 속성 가짐
? 상속받아야됨
SliverPersistentHeaderDelegate 상속받는 MyHeader 클래스 생성
CustomScrollView가 호출해서 높이 계산할때 쓰는 getter maxExtent, minExtent
pinned=true때문에 올리면 걸린다.
min은 올렸을때 걸리면서 줄어드는 사이즈


SliverFillViewport
Viewport - 화면을 꽉채움


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



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