Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-16 04:51
관리 메뉴

nomad-programmer

[Programming/Flutter] Sliver 애니메이션 효과 본문

Programming/Flutter

[Programming/Flutter] Sliver 애니메이션 효과

scii 2020. 10. 9. 13:58

SliverAppBar & SliverFillRemaining

SliverAppBar와 SliverFillRemaining은 화면 헤더를 동적으로 표현하는 위젯이다. 헤더를 위로 스크롤하면 헤더 부분이 작아지면서 헤더 하단에 있던 정적인 내용만 보이는 AppBar 형태로 애니메이션된다. 이런 효과를 Sliver 효과라고 부른다.

실행되는 모습

SliverAppBar와 SliverFillRemaining을 사용한 예이다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: AnimatedContainerPageState(title: '플러터 테스트'),
    );
  }
}

class AnimatedContainerPageState extends StatefulWidget {
  AnimatedContainerPageState({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _AnimatedContainerPageStateState createState() =>
      _AnimatedContainerPageStateState();
}

class _AnimatedContainerPageStateState
    extends State<AnimatedContainerPageState> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            // 헤더 영역
            pinned: true, // 축소시 상단에 AppBar가 고정되는지 설정
            expandedHeight: 180.0, // 헤더의 최대 높이
            flexibleSpace: FlexibleSpaceBar(
              // 늘어나는 영역의 UI 정의
              title: new Text('Sliver'),
              background: Image.asset(
                'assets/IMG_9245.jpeg',
                fit: BoxFit.cover,
              ),
            ),
          ),
          SliverFillRemaining(
            // 내용 정의
            child: new Center(
              child: new Text('center'),
            ),
          ),
        ],
      ),
    );
  }
}

Scaffold의 appBar를 지정하지 않고 body에 CustomScrollView의 인스턴스를 지정했다. 그리고 CustomScrollView의 slivers 프로퍼티에 SliverAppBar와 SliverFillRemaining 위젯을 설정한다.

SliverAppBar 위젯의 Sliver 효과를 위한 최소한의 프로퍼티는 pinned, expandedHeight, flexibleSpace이다.

  • pinned : 축소될 때 상단에 AppBar가 고정될지 사라질지 설정한다.
  • expandedHeight : 확대될 때의 최대 높이를 정한다.
  • flexibleSpace : 확대/축소되는 영역의 UI를 작성한다.

flexibleSpace 위젯은 title과 background 프로퍼티를 활용하여 적절히 AppBar 영역이 확장되었을 때의 UI를 작성한다.

SliverFillRemaining 위젯에는 스크롤 영역에 표시될 화면을 정의한다.child에 작성한 내용의 크기가 작아도 SliverAppBar 부분이 축소될 때 딱 하나의 크기가 알아서 결정된다.


SliverAppBar & SliverList

위의 SliverFillRemainig 위젯은 하나의 정적인 화면을 구성할 때 사용하는 반면 아래의 그림처럼 ListView를 사용하며 Sliver 효과를 주고 싶다면 ListView 대신 SliverList를 사용해야 한다.

실행화면

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: SliverListPage(),
    );
  }
}

class SliverListPage extends StatelessWidget {
  // 'No. 0'에서 'No. 49'까지 표시하는 ListTile을 담은 리스트
  final List<ListTile> _items = List.generate(
      50,
      (index) => new ListTile(
            title: new Text('No. $index'),
          ));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            expandedHeight: 180.0,
            flexibleSpace: FlexibleSpaceBar(
              title: new Text('Sliver'),
              background: Image.asset(
                'assets/IMG_9245.jpeg',
                fit: BoxFit.cover,
              ),
            ),
            actions: <Widget>[
              IconButton(
                  icon: Image.asset('assets/github_icon.png'), onPressed: () {})
            ],
          ),
          SliverList(delegate: SliverChildListDelegate(_items)),
        ],
      ),
    );
  }
}

SliverList는 delegate 프로퍼티에 SliverChildListDelegate 클래스 인스턴스를 지정해야 한다. SliverChildListDelegate 클랫의 생성자에 표시할 위젯 리스트(_item)를 인수로 전달해야 하며 _items는 ListTile이 50개인 리스트이다.

Comments