애니메이션(4) 슬리버 스크롤뷰
화면을 스크롤할 때 앱바의 크기를 변경하는 애니메이션을 구현해보겠다.
앱바나 리스트를 역동적으로 만들고 싶을 때는 슬리버(sliver)라는 위젯을 사용한다.
SliverAppBar, SliverList, SliverGrid 등 세 가지 슬리버를 사용해 확장 앱바와 리스트, 그리드가 차례로 포함된
스크롤뷰를 만들어 보았다.
- sliverPage.dart 파일을 만든 뒤 StatefulWidget을 상속받는 SliverPage 클래스를 만들어 기본 골격을 갖춘다.
- body에서 사용한 CustomScrollView는 슬리버를 사용해 사용자 정의 스크롤 효과를 만드는 위젯이다. CustomScrollView의 slivers에 위젯을 지정하면 확장 앱바, 리스트, 그리드와 같은 다양한 스크롤 효과를 만들 수 있다.
- CustomScrollView의 slivers에 SliverAppBar를 사용해 확장 앱바를 만든다. 슬리버가 들어가는 위젯을 이용할 때는 컨테이너나 텍스트 등 기본적인 위젯을 바로 사용할 수 없고 slivers 인자로 위젯을 묶어주어야 한다.
- CustomScrollView의 slivers에 첫 번째 위젯으로 지정한 SliverAppBar는 특수한 위젯이라 일반 칼럼이나 리스트뷰에서는 사용할 수 없다. 오직 CustomScrollView에서만 사용할 수 있으며 스크롤에 따라 높이가 달라지거나 다른 위젯 위에 표시되도록 스크롤뷰에 통합된다.
- SliverAppBar에서는 expandedHeight를 이용해 앱바의 최대 높이를 설정하고 flexibleSpace를 이용해 유연하게 조절되는 공간을 만든 다음 FlexibleSpaceBar를 넣는다. FlexibleSpaceBar 위젯은 머티리얼 디자인 앱바를 확장하거나 축소, 스트레칭해준다. 여기에는 제목(title)과 배경(background) 이미지를 설정해 스크롤에 따라 크기가 조절되도록 해준다.
- 스크롤되는 위젯
- CustomScrollView의 slivers에 SliverList와 SliverGrid 위젯을 추가한다. 이때 SliverChildListDelegate를 선언해 배열 안에 원하는 위젯을 넣을 수 있도록 함수를 참조하는 델리게이트를 만들어준다.
- 슬러버 화면을 보면 리스트와 그리드가 표시되는 것을 볼 수 있고, 리스트를 쓸어 올려 스크롤을 내리면 앱바 영역이 점점 줄다가 사라지는 것을 확인할 수 있다.
위젯을 구분하는 머리말 추가하기
- SliverPersistenHeader를 이용하면 슬리버 위젯별로 헤더를 지정할 수 있다. SliverPersistentHeader를 사용하려면 SliverPersistentHeaderDelegate라는 델리게이트가 필요하다
- SliverPersistentHeaderDelegate를 상속받는 _HeaderDelegate 클래스를 이용해 델리게이트를 만들어 준다. math 패키지가 제공하는 max()함수를 사용하기 위해 import 문도 추가한다.
- _HeaderDelegate 클래스에서는 4개의 함수를 재정의했다.
1. build() : 함수의 머리말을 만들 때 사용할 위젯을 배치한다.
2. maxExtent() : 해당 위젯의 최대 높이를 설정한다.
3. math.max() : 가장 높은 값을 설정
4. minExtent() : 가장 작은 높이를 설정, 이 높이 이하로는 머리말의 크기가 줄어들지 않는다.
5. shouldRebuild() : 위젯을 계속 그릴 것인지 정한다. 만약 maxHeight나 minHeight, child가 달라진다면 true를 반환해 계속 다시 그릴 수 있게 설정한다.
- 작성한 SliverList와 SliverGrid위에 SliverPersistentHeader 위젯을 추가한다. 그리고 슬리버 앱바에 pinned라는 옵션은 true로 설정해 앱바가 사라지지 않고 최소의 크기로 고정되게 설정한다.
- 슬리버 화면에서 리스트를 스크롤해 보면 앱바가 사라지지 않고 고정되는 것을 확인할 수 있다. 그리고 리스트와 그리드가 나오기 전에 파랑 바탕의 머리말이 표시되고 스크롤하면 앱바처럼 줄어들다가 고정되는 것을 확인할 수 있다.