CustomScrollView, SliverAppBar

샤워실의 바보·2024년 2월 11일
0
post-thumbnail
post-custom-banner

두 위젯 CustomScrollViewSliverAppBar는 Flutter에서 스크롤 가능한 영역을 더 유연하게 구성할 때 유용합니다. 아래에서 두 위젯에 대한 설명을 제공하겠습니다.

CustomScrollView

  • CustomScrollView는 여러 개의 스크롤 가능한 영역을 조합해서 사용하려 할 때 유용한 위젯입니다.
  • 이 위젯은 'slivers'라는 다양한 스크롤 가능한 요소들과 함께 동작합니다.
  • ListViewGridView와는 달리 CustomScrollView는 그 자체로 아이템이나 자식들을 가지지 않습니다. 대신 slivers라는 속성을 통해 여러 sliver 위젯들을 자식으로 가질 수 있습니다.

Sliver의 의미

"Sliver"는 Flutter에서 사용하는 용어로, 특별한 종류의 스크롤 가능한 영역을 나타냅니다. 기본적으로, sliver는 스크롤 가능한 영역에서 여러 부분으로 나눌 수 있는 작은 조각(piece)을 의미합니다.

Flutter에서 "sliver"의 개념은 기본 ListView 또는 GridView와 같은 일반 스크롤 가능한 영역보다 더 정교한 스크롤 작업을 수행할 수 있도록 합니다. 예를 들어, 사용자가 스크롤할 때 헤더가 축소되는 효과나 동적으로 아이템이 배치되는 레이아웃 등을 구현하기 위해 sliver 위젯을 사용할 수 있습니다.

Flutter에는 다양한 sliver 위젯이 포함되어 있습니다. 예를 들면:

  • SliverList: 일반 리스트와 유사하게 아이템을 세로로 나열합니다.
  • SliverGrid: 그리드 형태의 아이템 배치를 지원합니다.
  • SliverAppBar: 스크롤에 반응하는 앱 바입니다.
  • SliverToBoxAdapter: 단일 위젯을 sliver로 변환합니다.

이러한 sliver 위젯들은 주로 CustomScrollView 내에서 사용되며, 이를 통해 다양한 스크롤 효과와 레이아웃을 구현할 수 있습니다.

요약하면, "sliver"는 Flutter에서 스크롤 가능한 영역의 작은 부분 또는 조각을 나타내며, 이를 활용하면 다양하고 정교한 스크롤 작업을 수행할 수 있습니다.

SliverAppBar

  • SliverAppBarCustomScrollView의 일부로 사용되며, 스크롤 행동에 따라 애니메이션 효과를 적용할 수 있는 앱 바입니다.
  • 이 위젯은 전통적인 앱 바와는 달리, 사용자가 스크롤할 때 확장되거나 축소되는 등의 다양한 애니메이션 효과를 적용할 수 있습니다.

주요 속성:

  1. pinned: true로 설정하면 작은 앱 바로 축소되지만 스크롤 영역의 상단에 '고정'됩니다.

  2. floating: 이 속성이 true로 설정되면, 사용자가 스크롤을 시작할 때 SliverAppBar가 즉시 나타나게 됩니다. 일반적으로 사용자가 목록의 맨 위로 돌아갈 필요 없이 스크롤을 조금만 움직여도 SliverAppBar를 빠르게 다시 볼 수 있게 하려고 사용합니다. 반면에 floatingfalse로 설정되면, 사용자는 스크롤 위치를 목록의 맨 위로 되돌려야만 SliverAppBar를 다시 볼 수 있습니다.

  3. expandedHeight: 앱 바가 확장될 때의 최대 높이입니다.

  4. flexibleSpace: 확장 가능한 공간 안에 배치될 위젯, 예를 들면 배경 이미지 등을 설정할 때 사용합니다.

예시:

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      expandedHeight: 200.0,
      floating: false,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        title: Text("SliverAppBar Example"),
        background: Image.network(
          "https://some-image-url.com",
          fit: BoxFit.cover,
        ),
      ),
    ),
    // 다른 slivers...
  ],
)

이 예제에서는 SliverAppBarCustomScrollView의 일부로 사용되고 있으며, 앱 바는 확장될 때 200 픽셀의 높이를 가집니다. 또한 앱 바는 스크롤 영역의 상단에 항상 고정되어 있습니다. FlexibleSpaceBar를 사용하여 앱 바에 제목과 배경 이미지를 추가하였습니다.

import 'package:flutter/material.dart';
import 'package:tiktok_clone/constants/sizes.dart';

class UserProfileScreen extends StatefulWidget {
  const UserProfileScreen({super.key});

  
  State<UserProfileScreen> createState() => _UserProfileScreenState();
}

class _UserProfileScreenState extends State<UserProfileScreen> {
  
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverAppBar(
          pinned: true,
          stretch: true,
          backgroundColor: Colors.teal,
          collapsedHeight: 80,
          expandedHeight: 200,
          flexibleSpace: FlexibleSpaceBar(
            stretchModes: const [
              StretchMode.blurBackground,
              StretchMode.zoomBackground,
              StretchMode.fadeTitle,
            ],
            background: Image.asset(
              "assets/images/placeholder.jpg",
              fit: BoxFit.cover,
            ),
            title: const Text("Hello!"),
          ),
        ),
        SliverFixedExtentList(
          delegate: SliverChildBuilderDelegate(
            childCount: 50,
            (context, index) => Container(
              color: Colors.amber[100 * (index % 9)],
              child: Align(
                alignment: Alignment.center,
                child: Text("Item $index"),
              ),
            ),
          ),
          itemExtent: 100,
        ),
        SliverGrid(
          delegate: SliverChildBuilderDelegate(
            childCount: 50,
            (context, index) => Container(
              color: Colors.blue[100 * (index % 9)],
              child: Align(
                alignment: Alignment.center,
                child: Text("Item $index"),
              ),
            ),
          ),
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 100,
            mainAxisSpacing: Sizes.size20,
            crossAxisSpacing: Sizes.size20,
            childAspectRatio: 1,
          ),
        )
      ],
    );
  }
}

이 코드는 Flutter에서 사용자 프로필 화면을 구성하는 예제입니다. 코드에는 주로 CustomScrollView, SliverAppBarSliverFixedExtentList 위젯이 사용되었습니다. 이 코드의 구성 요소에 대해 상세히 설명하겠습니다.

  1. UserProfileScreen:

    • StatefulWidget 기반의 사용자 프로필 화면입니다.
    • 상태를 관리하기 위해 _UserProfileScreenState를 사용합니다.
  2. CustomScrollView:

    • 스크롤 가능한 영역 안에 여러 "slivers" 위젯들을 자식으로 가질 수 있는 위젯입니다.
  3. SliverAppBar:

    • 스크롤 동작에 따라 변형되는 앱 바입니다.
    • snap, floating, pinned, stretch 속성들이 사용되어 다양한 애니메이션 및 동작을 설정합니다.
    • collapsedHeight는 앱 바가 축소될 때의 높이를, expandedHeight는 앱 바가 확장될 때의 높이를 지정합니다.
    • flexibleSpaceFlexibleSpaceBar를 사용하여 앱 바 내에서 동적으로 크기가 조정되는 공간을 정의합니다.
  • Flutter에서 SliverAppBar는 사용자의 스크롤에 따라 그 동작과 모양이 변하는 매우 유연한 앱 바 위젯입니다. 코드 스니펫에서 snap, floating, pinned, stretch 속성들은 SliverAppBar의 동작 방식을 제어합니다. 각 속성에 대해 살펴보겠습니다:

snap: true

  • 동작: snaptrue로 설정되면, 스크롤이 멈추었을 때 앱 바가 완전히 나타나거나 완전히 사라집니다. 이 속성은 floatingtrue로 설정된 경우에만 효과가 있습니다.
  • 사용 사례: 사용자가 스크롤할 때 앱 바를 빠르게 드러내거나 숨기는 데 유용하며, 쾌적한 사용자 경험을 제공합니다.

floating: true

  • 동작: floating 앱 바는 사용자가 위로 스크롤하기 시작하면 바로 보이게 됩니다. 스크롤 뷰의 시작 부분에 도달할 필요가 없습니다.
  • 사용 사례: 사용자가 전체 목록을 처음부터 다시 스크롤할 필요 없이 앱 바 옵션에 쉽게 접근하고 싶을 때 긴 목록이나 콘텐츠에 특히 유용합니다.

pinned: true

  • 동작: pinnedtrue일 때, 앱 바는 스크롤 뷰 상단에 계속 보이게 됩니다. 하지만 앱 바의 나머지 내용은 스크롤과 함께 사라지고 도구 모음 부분만 남습니다.
  • 사용 사례: 항상 앱 바를 보이게 하고 싶지만, 탄력적인 공간(예: 이미지)을 사용하여 스크롤과 함께 사라지게 하고 싶을 때 사용합니다.

stretch: true

  • 동작: stretch가 활성화되면, 사용자가 상단에서 오버 스크롤할 때 앱 바가 늘어나고 크기가 확장됩니다.
  • 사용 사례: 이는 시각적으로 늘어나는 효과를 만들어내며, 특히 탄력적인 배경 공간과 결합할 때 매력적입니다.

결합된 동작

snap: true, floating: true, pinned: true, stretch: true를 함께 사용하면 SliverAppBar는:

  • 상단에 고정되어 항상 보이게 됩니다 (pinned).
  • 사용자가 스크롤 위치에 관계없이 위로 스크롤하기 시작하면 나타납니다 (floating).
  • 스크롤이 멈출 때 보이거나 사라지는 스냅 효과가 있습니다 (snap).
  • 사용자가 상단에서 오버 스크롤할 때 늘어납니다 (stretch).

이 조합은 사용자 상호작용에 따라 조정되는 매우 동적이고 상호작용적인 앱 바를 만들어내며, 화면 공간 최대화와 사용자 경험을 우선시하는 현대 모바일 애플리케이션에서 일반적으로 사용되는 패턴입니다.

  1. FlexibleSpaceBar:

    • 앱 바의 유연한 공간에 배경 및 제목과 같은 내용을 추가합니다.
    • stretchModes는 앱 바가 확장될 때 어떤 방식으로 확장될 것인지를 정의합니다. 여기서는 배경 흐리게하기, 배경 확대, 제목 사라지게하기 등의 모드가 사용되었습니다.
    • background에서는 배경 이미지를 설정합니다.
  2. SliverFixedExtentList:

    • 고정된 높이를 가진 아이템들로 구성된 스크롤 가능한 리스트입니다.
    • delegate는 리스트의 아이템들을 구성하기 위해 SliverChildBuilderDelegate를 사용하여 50개의 아이템을 생성합니다.
    • 각 아이템은 다양한 색상의 컨테이너로, 중앙에 "Item $index"라는 텍스트가 표시됩니다.
    • itemExtent는 각 아이템의 높이를 지정합니다.

이 코드를 실행하면, 사용자는 상단의 유연한 앱 바를 볼 수 있으며, 확장 및 축소 애니메이션 효과가 적용됩니다. 아래쪽에는 50개의 아이템이 고정된 높이로 표시되는 리스트가 있습니다.

SliverFixedExtentList는 Flutter에서 스크롤 가능한 영역 내에 고정된 높이를 가진 아이템들로 구성된 리스트를 생성하는 위젯입니다. Sliver 위젯들은 CustomScrollView 내에서 사용될 수 있습니다.

SliverFixedExtentList의 주요 특징과 속성을 상세하게 살펴보겠습니다:

  1. 기본 개념:

    • SliverFixedExtentList는 모든 자식 아이템들이 동일한 높이를 가질 것이라는 가정하에 최적화된 스크롤 가능한 리스트를 제공합니다. 각 아이템의 높이가 동일하기 때문에 Flutter는 더 빠르게 스크롤 및 렌더링 작업을 수행할 수 있습니다.
  2. itemExtent:

    • 이 속성은 각 아이템의 높이를 지정합니다. 모든 아이템은 이 높이를 기반으로 렌더링됩니다.
  3. delegate:

    • 이 속성은 리스트의 내용을 구성하는 방법을 정의합니다. 대부분의 경우, SliverChildBuilderDelegate 또는 SliverChildListDelegate를 사용하여 아이템들을 정의합니다.
    • SliverChildBuilderDelegate를 사용하면 지연 로딩이 가능하며, 요청 시점에 각 아이템을 생성할 수 있습니다. 따라서 무한한 수의 아이템이나 매우 큰 수의 아이템을 갖는 리스트를 생성할 때 유용합니다.
  4. 사용 사례:

    • 코드 예제에서는 SliverFixedExtentList를 사용하여 50개의 아이템을 생성합니다. 각 아이템은 SliverChildBuilderDelegate에 의해 생성되며, 다양한 색상의 컨테이너로 표시됩니다. 아이템의 중앙에는 "Item $index"라는 텍스트가 표시됩니다.

이 위젯은 특히 아이템의 크기가 동일한 경우나 리스트의 크기가 동적으로 변하지 않는 경우에 유용하게 사용됩니다. 동일한 높이의 아이템으로 구성된 리스트를 빠르게 스크롤하고 렌더링해야 하는 경우에는 SliverFixedExtentList가 효율적인 선택이 될 수 있습니다.

profile
공부하는 개발자
post-custom-banner

0개의 댓글