[Flutter] NestedScrollView_00

YOUN·2023년 8월 18일
0

Flutter

목록 보기
5/12

Sliver위젯들과 함께 복잡?한 스크롤 동작을 구현할 때 사용되곤 한다.
예를 들어 instagram에서 프로필을 보면

  1. 프로필 아이디(+ 편집 또는 수정 버튼)
  2. 프로필 정보(사진, 팔로우 수, 소개글 등)
  3. TabBar 아이콘 버튼(게시물, 내가 태그된 사진 등을 볼 수 있는 아이콘 탭)
  4. 탭에 따른 게시물

이러한 순으로 되어있다.

화면 전체는 스크롤뷰로, 위아래로 스크롤이 되며
탭 바 아이콘 버튼을 누르면 해당하는 게시물 탭을 보여준다.
해당하는 게시물 탭은 m * 3 메트릭스 형태로 되어 있다.
해당하는 게시물을 스크롤 해서 내리다보면 TabBar가 화면 최상단에 걸리게 된다.

이러한 복잡?한 스크롤 동작을 위해서 NestedScrollView를 사용한다.
위의 1~4의 번호 순서로 코드를 작성한다!

  1. TabBar를 사용하려면 제일 바깥쪽에 DefaultTabController로 감싸줘야 하는데 스크롤을 하다보면 화면 최상단에 시간과 배터리등의 정보와 겹쳐 질 수 있다. 따라서 이것을 피하기 위해 가장 바깥쪽을 SafeArea 위젯으로 감싸준다. TabBar는 2개이기 때문에 length는 2로 한다. 이후 NestedScrollView를 선언한다.
return SafeArea(
      child: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [ ...
  1. Sliver위젯 중 SliverAppBar를 선언하고 프로필 이름과 설정, 편집 등의 버튼을 생성한다. AppBar위젯과 매우 비슷!
return SafeArea(
      child: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverAppBar(
                title: const Text('NYAGU'),
                actions: [
                  IconButton(
                    onPressed: () {},
                    icon: const FaIcon(
                      FontAwesomeIcons.gear,
                      size: Sizes.size20,
                    ),
                  ),
                ],
              ),
  1. 프로필 정보를 만들기 위해 SliverToBoxAdapter을 선언한다. children에다가 와라랄라 작성!
return SafeArea(
      child: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverAppBar(
                title: const Text('NYAGU'),
                actions: [
                  IconButton(
                    onPressed: () {},
                    icon: const FaIcon(
                      FontAwesomeIcons.gear,
                      size: Sizes.size20,
                    ),
                  ),
                ],
              ),
              SliverToBoxAdapter(
                child: Column(
                  children: [ ...이것저것 작성
  1. TabBar를 만들어야하는데 스크롤을 내릴 시 화면 최상단에 걸려야하기 때문에 작성법이 조금 다르다. SliverPersistentHeader를 선언 후 delegate로 사용할 PersistentTabBar클래스를 새롭게(extends) 우선 작성한다.
    PersistentTabBar클래스에서 바로 TabBar를 작성하려고 했으나 디자인?때문에 decoration한 Container안에 TabBar를 만들었다. 그냥 바로 TabBar를 작성해도 무방!
class PersistentTabBar extends SliverPersistentHeaderDelegate {
  
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      decoration: BoxDecoration( ...
      ),
      child: const TabBar(
        indicatorColor: Colors.black,
        indicatorSize: TabBarIndicatorSize.label,
        labelColor: Colors.black,
        tabs: [
          Tab( ...
          Tab( ...
        ],
      ),
    );
  }

  
  double get maxExtent => 47;

  
  double get minExtent => 47;

  
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}

이후 이하와 같이 작성하면 계속 아래로스크롤해도 최상단에 TabBar가 걸리는 스크롤 뷰 완성!

return SafeArea(
      child: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverAppBar( ...
              SliverToBoxAdapter( ...
              SliverPersistentHeader(
                  delegate: PersistentTabBar(), pinned: true),
            ];
          },
  1. 탭에 따른 게시물은 NestedScrollView의 body에다가 작성한다.
return SafeArea(
      child: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverAppBar( ...
              SliverToBoxAdapter( ...
              SliverPersistentHeader(
                  delegate: PersistentTabBar(), pinned: true),
            ];
          },
          body: TabBarView(
            children: [
              GridView.builder( ... 
              GridView.builder( ... 

메트릭스 형태로 표시하는 GridView에 대해서는 다음 포스팅에..

profile
SugarFree

1개의 댓글

comment-user-thumbnail
2023년 8월 18일

좋은 정보 감사합니다

답글 달기