[Flutter 심화] 5. Sliver (3) - NestedScrollView

김주희's avatar
Aug 04, 2025
[Flutter 심화] 5. Sliver (3) - NestedScrollView
NestedScrollView
이웃과 인접한 스크롤뷰
스크롤뷰 안에 스크롤뷰 넣을 수 있음
높이를 지가 측정해줌
sliver는 안에 있는 ? 계산해서 이벤트를 처리함
NestedScrollView는 ? 안해도 됨
 
headerSliverBuilder
body에 탭바 뷰를 가진애를 넣어
 
그러면 높이를 내가 안잡아도 됨
 
headerSliverBuilder 안에 sliver들이 들어가야 해서 그냥 container가 들어가면 터진다.
SliverToBoxAdapter 사용해서 Container 넣어야 됨
 
탭바가 걸림
 
NestedScrollView는 언제 쓰는가? 부모가 스크롤을 가졌을때 자식도 스크롤을 가질 수 잇는데 스크롤이 2개 됨 스크롤이 2개일 때 어느 스크롤로 움직일 지 정해야됨 NestedScrollView는 최상단의 부모만 감지함 자식(탭바뷰)의 스크롤은 무시됨 sliverpersistanceheader 기능..? 바디에 넣으면 딱 걸려있는 기능을 제공? (아니면 sliverList와 동일함)
 
Bottom 클래스를 SliverToBoxAdapter로 감싸서 넣으면 안되는 이유? 탭바여서 body에 넣어야 됨 headerSliverBuilder 가 아니라 탭바가 아니면 NestedScrollView를 쓸 필요 없음 탭바 내부에 스크롤이 있으면 무조건 body에 넣어야 됨 왤까?? 갈때 계산하니까 header는 미리 계산해야됨 header = 특정 영역은 계산해서 슬리버로 쓸게 body는 남는 공간을 잡아서 탭바를 눌릴때 사이즈가 결정나니까 일단 body 영역을 다 잡아! 탭바는 높이를 미리 계산하려면 전부 다 해야되고 불가능함 (탭바 중에서 제일 긴거 할거임? 화면마다 다를 수도 있는데)
 
전체가 스크롤이고 그 안에 스크롤 넣고 싶을 때 - SliverList 그리고
전체가 스크롤이고 탭바 넣을거임 그리고 그 안에 스크롤 잇음 - 계산이 안되는 영역이 있음 → NestedScrollView 사용
 
 

전체 코드

import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData(useMaterial3: true), home: ProfilePage(), ); } } class ProfilePage extends StatelessWidget { ProfilePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("title"), ), body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) { return [ SliverToBoxAdapter(child: Container(height: 200, color: Colors.red)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.yellow)), ]; }, body: Bottom(), ), ); } } class Bottom extends StatelessWidget { @override Widget build(BuildContext context) { return DefaultTabController( length: 2, child: Column( children: [ TabBar( tabs: [ Tab(icon: Icon(Icons.accessibility_new_outlined)), Tab(icon: Icon(Icons.account_circle_sharp)), ], ), Expanded( child: TabBarView( children: [ GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5, ), itemBuilder: (context, index) => SizedBox( height: 200, child: Image.network( "https://picsum.photos/id/${200 + index}/200/300", fit: BoxFit.cover, ), ), itemCount: 30, ), Container(color: Colors.red), ], ), ), ], ), ); } }
Share article

jay0628