본문 바로가기
flutter/Widget of the Week

Flutter[플러터] / SliverAppBar를 사용하여 커스텀 스크롤뷰 안에서 앱 바 사용하기 (사용법, CustomScrollView, NestedScrollView, 속성) SliverAppBar (Flutter Widget of the Week)

by ch5c 2025. 7. 14.
반응형

SliverAppBar class

CustomScrollView 와 통합된 Material Design 앱 바입니다.

앱 바는 툴바와 TabBar , FlexibleSpaceBar 등의 다른 위젯으로 구성됩니다. 앱 바는 일반적으로 하나 이상의 일반적인 동작을 IconButton 으로 표시하며 , 덜 일반적인 작업을 위해 PopupMenuButton이 뒤에 올 수도 있습니다.

https://youtu.be/R9 C5 KMJKluE

공식 문서 코드

 

 


우리가 CustomScrollView를 사용하다 보면 내부에서 앱 바를 사용하고 싶을 때가 있다. 하지만 appBar 같은 파라미터가 존재하지도 않고 AppBar 위젯은 넣을 수도 없게 되어 있다. 이럴 때 커스텀 스크롤뷰 안에서 앱 바를 어떻게 삽입할 수 있을까? 바로 SliverAppBar위젯을 사용하면 된다.

SliverAppBarCustomScrollViewNestedScrollView와 함께 사용할 수 있는 AppBar 위젯으로, 스크롤 동작에 따라 확장되거나 축소될 수 있는 유연한 앱 바를 제공해 준다. 일반적인 AppBar보다 더 많은 유저 인터랙션을 가능하게 하며, 스크롤에 따라 동적으로 변형되는 UI를 만들 때 유용하게 사용된다. 바로 알아보자.

하위 속성
속성명 타입 기본값 설명
leading Widget? null 앱바 왼쪽에 배치할 위젯
automaticallyImplyLeading bool true leading이 없을 때 자동으로 뒤로가기 버튼 등을 삽입할지 여부
title Widget? null 앱바의 타이틀로 표시될 위젯
actions List<Widget>? null 앱바 오른쪽에 배치할 위젯 리스트
flexibleSpace Widget? null 스크롤에 따라 확장될 공간에 표시할 위젯
bottom PreferredSizeWidget? null 앱바 아래에 표시할 추가 위젯
elevation double? null 앱바의 그림자 깊이
scrolledUnderElevation double? null 내용이 스크롤될 때 적용할 elevation
shadowColor Color? null 그림자 색상
surfaceTintColor Color? null 표면 틴트 색상
forceElevated bool false 스크롤되지 않았어도 elevation을 강제로 적용할지 여부
backgroundColor Color? null 앱바 배경색
foregroundColor Color? null 타이틀과 아이콘 등의 전경색
iconTheme IconThemeData? null 아이콘 테마 스타일
actionsIconTheme IconThemeData? null actions 영역의 아이콘 테마 스타일
primary bool true 상단 시스템 영역 포함 여부
centerTitle bool? null 타이틀을 중앙에 정렬할지 여부
collapsedHeight double? null 앱바가 축소되었을 때의 높이
expandedHeight double? null 앱바가 확장되었을 때의 최대 높이
floating bool false 스크롤을 올릴 때 앱바가 즉시 나타나도록 할지 여부
pinned bool false 또는 true 앱바가 스크롤 시 항상 상단에 고정될지 여부
snap bool false floating 상태에서 앱바를 스냅 애니메이션으로 보여줄지 여부
stretch bool false 오버스크롤 시 앱바가 늘어날지 여부
onStretchTrigger AsyncCallback? null stretch 트리거 콜백
toolbarHeight double kToolbarHeight 툴바의 기본 높이
systemOverlayStyle SystemUiOverlayStyle? null 시스템 오버레이 아이콘 색상 설정
clipBehavior Clip? null 클리핑 방식 설정
actionsPadding EdgeInsetsGeometry? null actions 영역의 패딩 설정

 

기본적으로 사용하기 위해선 CustomScrollView 혹은 NestedScrollView내부여야 한다.

커스텀 스크롤뷰 내에서 위젯을 배치하려면 slivers 파라미터 안에 아래와 같이 넣어주면 된다.

CustomScrollView(
  slivers: [
    SliverAppBar(),
  ],
)

이제 이렇게만 해줘도 기본적인 사용 준비는 완료된 것이다.

기본적인 준비가 완료되었으니 가장 기본적인 텍스트를 앱바에 삽입해 보자.

title 파라미터에 Text 같은 텍스트 위젯을 삽입하여 제목을 만들어 줄 수 있다.

SliverAppBar(
  title: Text('타이틀!'),
)

여기서 뒤로 가기 아이콘이나 목록 아이콘을 배치하고 싶다면 leading 속성을 활용해 주면 된다.

SliverAppBar(
  leading: Icon(Icons.arrow_back),
  title: Text('타이틀!'),
)

이제  slivers 파라미터 안에 사이즈를 먹는 위젯을 배치하여 스크롤을 해보자.

CustomScrollView(
  slivers: [
    SliverAppBar(leading: Icon(Icons.arrow_back), title: Text('타이틀!')),
    SliverList(
      delegate: SliverChildBuilderDelegate((context, index) {
        return Container(
          color: index.isOdd ? Colors.white : Colors.black12,
          height: 100,
          child: Center(
            child: Text(
              index.toString(),
              textScaler: const TextScaler.linear(5),
            ),
          ),
        );
      }, childCount: 20),
    ),
  ],
),

실행을 해보면 기존 앱바와는 다르게 스크롤을 하면 그냥 그 자리에 고정되어 있는 위젯처럼 스크롤을 따라오지 않고 그냥 화면 너머로 넘어가게 된다.

그 이유가 무엇이냐 하면 SliverAppBar의 동작을 제어해 주는 파라미터들이 있는데 그 기본값들은 전부 false로 설정되어 있기 때문이다. 그렇다면 그 동작을 제어해 주는 파라미터들은 어떠한 것들일까?

그 동작을 제어해 주는 파라미터는 floating, pinned, snap이 총 3개가 되시겠다.

각각 동작들을 알아보자면 먼저 floating은 스크롤을 올릴 때 앱바가 즉시 나타나도록 할지 여부이다. 그다음 pinned은 앱바가 스크롤 시 항상 상단에 고정될지 여부에 대한 파라미터이고 마지막으로 snap은 floating 상태에서 앱바를 스냅 애니메이션으로 보여줄지 여부를 나타내게 된다. 근데 솔직히 스냅은 나도 왜 있는지 잘 모르겠다;;

아래는 그 3개의 값에 대한 동작들이다.

floating: false, pinned: false, snap: false

floating: true, pinned: false, snap: false

floating: true, pinned: false, snap: ture

floating: true, pinned: ture, snap: false
floating: true, pinned: true, snap: true

floating: false, pinned: true, snap: false

 

이렇게 속성을 부여할 수 있다는 건 이제 알았는데 그렇다면 상세하게 조절도 가능해야 할 것이다.

expandedHeight 파라미터와 flexibleSpace 파라미터를 사용하여 가능한 높이까지 확장되는 유연한 공간을 생성할 수 있게 된다.

여기서 먼저 double타입을 가진 expandedHeight을 사용하여 앱바를 자신이 확장하고 싶은 만큼 확장해 주자.

expandedHeight: 150,

이렇게 해놓고 슬라이버 목록 상단에 도달하게 되면 앱바가 자신이 설정해 놓은 값만큼 확장되게 된다.

이제 여기에서 flexibleSpace파라미터에 FlexibleSpaceBar위젯을 사용하여 이 SliverAppBar를 한층 더 유연하게 꾸며줄 수 있게 된다.

SliverAppBar(
  expandedHeight: 150,
  flexibleSpace: FlexibleSpaceBar(
    background: Image.asset('assets/faker.jpeg', fit: BoxFit.cover,),
    title: Text('T1', style: TextStyle(color: Colors.red),),
  ),
  leading: Icon(Icons.info),
),

참고로 기존에 flexibleSpace파라미터 바깥에서 사용했던 타이틀이나 리딩 아이콘도 다 유지가 된다.

또한 background 파라미터를 사용해 주면 타입이 Widget?이기 때문에 어떠한 위젯이든 다 배경으로 넣어줄 수 있게 된다.

마지막으로 스크롤 시 앱바를 아래로 당길 때 늘어나는 효과를 설정해 줄 수도 있다.

먼저 SliverAppBar에서 기본값이 falsestrechtrue로 설정해 준다.

stretch: true,

또한 스크롤 효과를 조절해 줄 수 있는 physicsBouncingScrollPhysics를 먹여준다. 이제 실행해 보면 앱바가 쫙쫙 늘어날 것이다.

CustomScrollView(
  physics: BouncingScrollPhysics(),

그런 다음 다시 FlexibleSpaceBar안으로 돌아와서 stretchModes를 사용해 줄 수 있는데 이 위젯 안에서 스크롤 시 앱바를 아래로 당길 때 나타나는 효과를 설정해 줄 수 있다.

SliverAppBar(
  stretch: true,
  expandedHeight: 150,
  flexibleSpace: FlexibleSpaceBar(
    background: Image.asset('assets/faker.jpeg', fit: BoxFit.cover),
    title: Text('T1', style: TextStyle(color: Colors.red),),
    stretchModes: <StretchMode>[
      StretchMode.blurBackground, // 블러 효과
      StretchMode.zoomBackground // 줌 효과
    ],
  ),
  leading: Icon(Icons.info),
)

이렇게 속성들을 잘 조합하묜 원하는 모양의 앱바를 만들어 낼 수 있게 된다.

SliverAppBar위젯은 나도 꽤 좋아하는 위젯 중에 하나인 게 일단 앱바가 막 사라졌다가 늘어났다가 붙었다가 그러면 기본적으로 재밌다. 근데 이 위젯에 사소한 문제점이 하나 있는데 그냥 색 지정해 놓으면 내려갈 때 뭐 색이 중첩이 되는지 버그가 있는지 색이 진해진다. 근데 이게  바꿀 방법이 없다.. 암튼 도움이 되었길 바라며 마치겠다.

반응형