[Flutter] - SliverAppBar 사용 방법
Flutter

[Flutter] - SliverAppBar 사용 방법

728x90

안녕하세요 오늘은 SliverAppBar 사용 방법에 대해 설명드리겠습니다.

Body에 List뷰를 사용했을때 상단 AppBar가 확장되거나 
내가 스크롤하는 움직임에 따라서 변화를 주고 싶을 때 주로 사용합니다. 

 

기본 위젯에 요소가 너무 많아서 제가 쓰면서 가장 필요하다고 생각했던 것들 위주로 정리해봤습니다. 

 

일단 구현 화면은 다음과 같습니다. 

하단 사진을 보시면 body부분엔 Listview가 AppBar에는 Image가 들어가 있는 형태로 구성되어 있습니다.

 

그럼 이렇게 구현하려면 어떤 방식을 사용해야 하는지 지금 부터 알아보도록 하겠습니다. 

 

1. slivers를 CustomScrollView로 감싸주자 

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: CustomScrollView(
      slivers: []
    ),
  );

 

Scaffold의 body를 CustomScrollView형태로 감싸줍니다. 
CustomScrollView란 sliver에 다른 스크롤 변화를 주고싶을때 쓰는 스크롤 뷰를 의미합니다. 

CustomScrollView의 Properties는 대표적으로 쓰이는 게

 

- controller
- scrollBehavior

- physics 
정도로 보시면 될거같습니다. 

//glow 해결용 -> glow란 ListView가 끝단에 다다를때 Glow가 발생
scrollBehavior: NoGlow(),
//physics 물리 - 원하는 UI에 맞춰 작업하면 됨
// NeverScrollableScrollPhysics : 목록 스크롤 불가능하게 설정
// BouncingScrollPhysics : 튕겨저 올라가는 듯한 동작 가능 List 끝에 도달했을 시에 다시 되돌아감
// ClampingScrollPhysics : 안드로이드의 기본 스크롤과 동일하다. List의 끝에 도달하면 동작을 멈춤
// PageScrollPhysics : 다른 스크롤에 비해 조금더 부드럽게 만듬
physics: ClampingScrollPhysics(),

Glow 해결 class

class NoGlow extends ScrollBehavior {
  @override
  Widget buildViewportChrome(
      BuildContext context, Widget child, AxisDirection axisDirection) {
    return child;
  }
}

사용하는 이유는 당연히 저희 목적인 SliverAppBar를 만들 수 있기 때문입니다. 

 

2. slivers[] 에 SliverAppBar 추가하기 

 

SliverAppBar의 Properties들이 굉장히 많이 있습니다.

공식 링크 : https://api.flutter.dev/flutter/material/SliverAppBar-class.html#instance-properties

 

SliverAppBar class - material library - Dart API

A material design app bar that integrates with a CustomScrollView. An app bar consists of a toolbar and potentially other widgets, such as a TabBar and a FlexibleSpaceBar. App bars typically expose one or more common actions with IconButtons which are opti

api.flutter.dev

다양한 요소들은 공식 링크를 참조하시면 되고 
자주 쓰이는 제가 개발하면서 사용했던 위주로 정리했습니다. 

 

SliverAppBar(
  //SliverAppBar의 높이 설정
  toolbarHeight: 50.0,
  //SliverAppBar의 backgroundcolor
  backgroundColor: Colors.green,
  //하단 List를 최상단으로 올렸을때의 SliverAppBar의 Default height
  //expandedHeight를 사용하면 스크롤을 내리면 toolbarheight높이까지 줄어든다.
  expandedHeight: 100.0,
  //SliverAppBar의 그림자 정도
  elevation: 0.0,
  //SliverAppBar title
  title: Text("sliver 1"),
  //SliverAppBar 영역을 고정시킨다. default false
  pinned: true,
  // AppBar가 하단 List 내렸을 때 바로 보여야 한다 -> true
  // List를 최상단으로 올렸을 때만 나와야 한다. -> false
  floating: true,
  ),

 

또한 나는 Appbar에 이미지도 넣고 하위 Widget을 넣어 구현하고 싶다 하시는 분들은 SliverAppBar 에 flexibleSpace를 넣어주심 됩니다.

 

            //title이 아니라 icon, image를 사용하여 flexible하게 조정하고 싶을땐 하단과 같이 코딩하면
            //원하는 출력물 구현이 가능하다.
            flexibleSpace: FlexibleSpaceBar(
              titlePadding: EdgeInsetsDirectional.only(
                top: 10,
                bottom: 0,
              ),
//make title centered.
              centerTitle: true,
              title: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  new Image.asset(
                    "images/test.png",
                    fit: BoxFit.fitWidth,
                    height: AppBar().preferredSize.height * 0.5,
                    width: 50,
                  ),
                ],
              ),
            ),

 

 

3. SliverList 작성 

다 작성해주셨으면 이제 하단 리스트를 구현하시면
상단 그림과 같이 구현이 가능합니다.

 

SliverList(
    delegate: SliverChildListDelegate(
        List.generate(items.length, (idx) {
          return Padding(
            padding: const EdgeInsets.only(left: 8.0, right: 8.0),
            child: Card(
              color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
              child: ListTile(
                leading: Icon(null),
                title: Text(items[idx]),
                onTap: null,
              ),
            ),
          );
        }),
)),

 

 

생각보다 간단하게 구현이 가능하며 
활용도가 높은 SliverAppBar에 대해 한번 제가 아는대로 적어 봤습니다. 


감사합니다. ! 

728x90