티스토리 뷰

목차



    반응형

    플러터에서 "Slivers"는 독특한 스크롤 인터페이스를 제공하는 중요한 위젯입니다. 특히 대규모 목록이나 스크롤이 필요한 화면에서 효율적이고 유연한 UI를 만드는 데 유용합니다. 이번 글에서는 Slivers의 개념과 기능, 대표적인 Sliver 위젯들, 그리고 실전 예제를 통해 플러터 개발에 Slivers를 활용하는 방법을 자세히 알아보겠습니다.

     

    1. Slivers란 무엇인가요?

    플러터에서 Slivers는 "부분적으로 그려지는 위젯"을 의미하며, 스크롤이 가능한 리스트나 그리드 레이아웃을 만들 때 주로 사용됩니다. 일반적으로 Flutter에서는 ListView와 GridView처럼 단순한 스크롤을 제공하는 위젯을 사용할 수 있지만, 더 유연하고 복잡한 스크롤 디자인이 필요할 때 Slivers를 사용하면 다양한 기능과 커스터마이징이 가능해집니다.

     

    Slivers의 가장 큰 장점은 스크롤 이벤트를 기반으로 위젯의 모양이나 레이아웃을 동적으로 변경할 수 있다는 것입니다. 예를 들어, 헤더 영역을 스크롤 시 숨기거나 줄어들게 하는 효과, 다단 그리드 레이아웃을 스크롤하며 펼쳐지게 하는 것 등이 가능합니다.

     

    2. 대표적인 Sliver 위젯 종류와 특징

    플러터에서는 다양한 Sliver 위젯을 제공하며, 주로 사용되는 Sliver 위젯은 다음과 같습니다.

     

    SliverAppBar: 스크롤할 때 크기가 변화하는 상단 앱바로, 스크롤에 따라 축소되거나 사라지는 동적인 헤더를 만듭니다.

    SliverList: 세로 방향의 스크롤 가능한 리스트를 생성합니다.

    SliverGrid: 가로 방향 그리드 형태의 스크롤 가능한 리스트를 만듭니다.

    SliverPadding: 슬리버의 주위에 패딩을 추가합니다.

    SliverToBoxAdapter: 일반 위젯을 Sliver 형태로 변환하여 사용하도록 합니다.

    SliverFillRemaining: 남은 화면 영역을 채우는 역할을 하는 위젯으로, 마지막에 추가하여 스크롤 가능한 레이아웃을 완성합니다.

     

    이제 Slivers의 대표적인 사용법을 각 예제를 통해 살펴보겠습니다.

     

    3. Sliver를 활용한 기본 예제: SliverAppBar와 SliverList

    SliverAppBar와 SliverList를 사용하여 스크롤 시 상단 바가 줄어들며 사라지는 앱을 만들어 보겠습니다.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: SliverExample(),
        );
      }
    }
    
    class SliverExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            slivers: [
              SliverAppBar(
                expandedHeight: 200.0,
                floating: false,
                pinned: true,  // true 일경우 appbar위치 고정(스크롤해도 고정되어있음)
                flexibleSpace: FlexibleSpaceBar(
                  title: Text("SliverAppBar Example"),
                  background: Image.network(
                    'https://example.com/header_image.jpg',
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) => ListTile(
                    title: Text("Item #$index"),
                  ),
                  childCount: 50,
                ),
              ),
            ],
          ),
        );
      }
    }

     

     

    위 예제에서는 CustomScrollView를 사용하여 SliverAppBar와 SliverList를 배치했습니다. SliverAppBar는 스크롤 시 점점 축소되며, 상단에 고정될 수 있습니다(pinned: true 옵션).

     

    4. SliverGrid 예제: 2열 그리드 구현

    SliverGrid를 활용하여 2열 그리드 형태의 스크롤 목록을 만들 수 있습니다. 그리드는 정사각형 또는 원하는 비율의 아이템들을 배열하는 데 유용합니다.

     

    class SliverGridExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            slivers: [
              SliverAppBar(
                expandedHeight: 200.0,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text("SliverGrid Example"),
                  background: Image.network(
                    'https://example.com/grid_header.jpg',
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              SliverGrid(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  mainAxisSpacing: 10.0,
                  crossAxisSpacing: 10.0,
                  childAspectRatio: 1.0,
                ),
                delegate: SliverChildBuilderDelegate(
                  (context, index) => Container(
                    color: Colors.teal[100 * (index % 9)],
                    child: Center(
                      child: Text('Grid Item $index'),
                    ),
                  ),
                  childCount: 20,
                ),
              ),
            ],
          ),
        );
      }
    }

     

     

    위 코드에서는 SliverGrid를 통해 2열 레이아웃을 설정했습니다. crossAxisCount 속성을 통해 열 수를 지정하며, childAspectRatio를 조정하여 아이템의 비율을 설정할 수 있습니다.

     

    5. SliverToBoxAdapter 예제: 일반 위젯과 함께 사용하기

    일반 위젯을 Sliver로 변환하여 활용할 때 SliverToBoxAdapter를 사용할 수 있습니다. 이를 통해 일반적인 Container, Image와 같은 위젯을 Sliver 레이아웃에 배치할 수 있습니다.

    class SliverToBoxAdapterExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            slivers: [
              SliverAppBar(
                expandedHeight: 150.0,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text("SliverToBoxAdapter Example"),
                ),
              ),
              SliverToBoxAdapter(
                child: Container(
                  height: 100,
                  color: Colors.amber,
                  child: Center(child: Text("Hello, Sliver!")),
                ),
              ),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) => ListTile(
                    title: Text("List Item #$index"),
                  ),
                  childCount: 15,
                ),
              ),
            ],
          ),
        );
      }
    }

     

    이 예제에서는 SliverToBoxAdapter로 일반 Container를 감싸서 CustomScrollView 안에 추가했습니다. 이를 통해 Sliver 위젯과 일반 위젯을 결합한 복합 레이아웃을 만들 수 있습니다.


    6. SliverFillRemaining 예제: 남은 공간 채우기

    마지막으로, SliverFillRemaining은 화면에서 남은 공간을 모두 차지하는 위젯을 만듭니다. 이 속성은 스크롤 가능한 레이아웃의 마지막에 추가하여 깔끔한 종료를 할 수 있습니다.

    class SliverFillRemainingExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            slivers: [
              SliverAppBar(
                expandedHeight: 150.0,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text("SliverFillRemaining Example"),
                ),
              ),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) => ListTile(
                    title: Text("List Item #$index"),
                  ),
                  childCount: 10,
                ),
              ),
              SliverFillRemaining(
                hasScrollBody: false,
                child: Container(
                  color: Colors.blueAccent,
                  child: Center(
                    child: Text(
                      "This fills the remaining space!",
                      style: TextStyle(color: Colors.white, fontSize: 20),
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }

     

    이 예제에서는 SliverFillRemaining을 사용해 마지막에 남은 공간을 파란색 배경의 텍스트 위젯으로 채웠습니다. hasScrollBody를 false로 설정하여 남은 공간을 모두 차지하도록 했습니다.


    7. 결론: Slivers의 유연한 활용으로 풍부한 UI 만들기

    플러터의 Slivers는 다양한 스크롤 인터페이스를 제공하여 앱의 사용자 경험을 크게 향상할 수 있습니다. 특히 대규모 데이터 리스트, 상단 고정 헤더, 그리드 레이아웃 등 다양한 스크롤 디자인이 필요한 경우 Slivers를 활용해보세요. 이를 통해 성능과 비주얼을 동시에 잡을 수 있습니다.

    반응형