Weekly Flutter

[Flutter Widget] 스크롤 가능한 레이아웃 만들기 - 1

ssuncake 2023. 2. 22. 17:00

Sliver란?

A sliver is a portion of a scrollable area that you can define to behave in a special way. You can use slivers to achieve custom scrolling effects, such as elastic scrolling.

사용자가 특수한 동작을 수행하도록 할 수 있고, 스크롤이 가능한 영역을 말합니다.

 

플러터에서 Sliver를 사용한 기본 위젯

Flutter에서는 ListView, GridView, SingleChildScrollView 등 Sliver를 사용하지 않는 스크롤 가능한 위젯을 기본으로 제공합니다. 이러한 위젯들은 간단하고 직관적이며, 일반적인 스크롤 동작을 구현하는 데 적합합니다.

 

언제 직접 만들어야 할까?

  1. 특정 디자인을 구현해야 하는 경우 일부 디자인 요구사항은 기본적인 스크롤 가능한 위젯으로 구현하기 어려울 수 있습니다. 이 경우에는 직접 Sliver를 사용하여 위젯을 만들어야 할 수 있습니다.
  2. 성능이 중요한 경우 Sliver는 성능이 우수하며, 대량의 데이터나 다양한 뷰를 가진 경우에도 빠르게 렌더링될 수 있습니다. 따라서, 대규모 스크롤 가능한 위젯을 구현해야 하는 경우에는 Sliver를 사용하여 직접 위젯을 만드는 것이 더 나은 성능을 제공할 수 있습니다.
  3. 특정 동작을 구현해야 하는 경우 Sliver를 사용하여 직접 위젯을 만들면, 특정 동작을 더욱 세밀하게 제어할 수 있습니다. 예를 들어, 스크롤 시 애니메이션을 적용하거나, 스크롤 위치에 따라 특정 요소를 보여주거나, 다른 위젯과 겹치는 효과 등을 구현할 수 있습니다.
  4. 다른 위젯과 연동해야 하는 경우 Sliver는 다른 위젯과 연동하여 다양한 스크롤 기능을 구현할 수 있습니다. 예를 들어, 다른 Sliver 위젯과 함께 사용하여 겹치는 효과를 구현하거나, SliverAppBar와 함께 사용하여 스크롤 시 앱 바를 확장 또는 축소하는 효과를 구현할 수 있습니다.

따라서, Sliver를 사용하여 직접 위젯을 만들어야 하는 경우는, 특정 디자인, 성능, 특정 동작, 다른 위젯과의 연동 등의 요구사항이 있을 때입니다. 하지만, 대부분의 경우에는 기본적인 스크롤 가능한 위젯을 사용하여 충분히 구현할 수 있으며, 필요한 경우에만 Sliver를 사용하여 위젯을 직접 만들면 됩니다.

 

 

Sliver를 사용하는 방법은 여러가지가 있습니다.

  1. CustomScrollView: Sliver 위젯을 사용하려면 일반적으로 CustomScrollView 위젯을 사용해야합니다. CustomScrollView는 여러 Sliver 위젯을 조합할 수 있습니다.
  2. SliverList와 SliverGrid: SliverList는 리스트 항목을 빌드하기 위해 사용됩니다. SliverGrid는 그리드 항목을 빌드하기 위해 사용됩니다. 이러한 위젯은 항목의 개수가 많거나 큰 경우에도 효율적인 렌더링을 제공합니다.
  3. SliverPersistentHeader: SliverPersistentHeader는 스크롤 가능한 화면 상단에 고정 된 헤더를 만드는 데 사용됩니다. 이 위젯은 스크롤 할 때 항상 화면 상단에 고정되어 유지됩니다.
  4. SliverAppBar: SliverAppBar는 앱 바를 스크롤 가능하게 만들어 줍니다. 앱 바가 스크롤 될 때 크기가 줄어 들고, 최상단에 고정 될 수 있습니다.
  5. SliverFillRemaining: SliverFillRemaining은 스크롤 가능한 화면의 남은 공간을 채우는 데 사용됩니다. 화면에 SliverList 또는 SliverGrid가 없을 때 이 위젯을 사용하여 스크롤 가능한 화면의 빈 공간을 채울 수 있습니다.
  6. NestedScrollView: NestedScrollView는 여러 스크롤 가능한 위젯을 중첩하여 사용할 수 있도록 도와줍니다. 예를 들어, 스크롤 가능한 헤더와 스크롤 가능한 리스트를 중첩하여 사용할 수 있습니다.

 

 

CustomScrollView를 사용하여 스크롤 방향이 다른 두개의 위젯을 넣어 화면을 만들어 보겠습니다.

  @override
  Widget build(BuildContext context) {
    final controller = ScrollController();
    const List<Color> colors = [
      Colors.amber,
      Colors.black,
      Colors.teal,
      Colors.white
    ];
    return Material(
      child: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: CustomScrollView(
                scrollDirection: Axis.horizontal,
                controller: controller,
                physics: AlwaysScrollableScrollPhysics(),
                slivers: List.generate(
                  10,
                  (index) => SliverToBoxAdapter(
                    child: Container(
                      // width: 100,
                      width: MediaQuery.of(context).size.width,
                      height: 200,
                      color: colors[index % colors.length],
                    ),
                  ),
                ),
              ),
            ),
            Expanded(
              child: CustomScrollView(
                scrollDirection: Axis.vertical,
                controller: controller,
                physics: AlwaysScrollableScrollPhysics(),
                slivers: List.generate(
                  10,
                  (index) => SliverToBoxAdapter(
                    child: Container(
                      width: MediaQuery.of(context).size.width,
                      height: 200,
                      color: colors[index % colors.length],
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

 

주요 속성

SliverDelegate : 슬리버 위젯에 대한 정보를 제공하는 추상 클래스입니다. 슬리버 위젯을 생성하고 관리하는 데 필요한 정보와 메서드를 포함하며, 해당 슬리버 위젯의 모양과 동작을 정의하는 데 사용됩니다. 예를 들어, SliverListDelegate는 목록에 대한 항목 수, 개별 항목의 높이 등의 정보를 제공합니다.

 

ScrollPhysics : 스크롤에 대한 물리학적 규칙을 정의하고, 사용자의 스크롤 동작에 응답하여 스크롤 위치를 업데이트합니다.

  • BouncingScrollPhysics: iOS 스타일의 바운스 효과를 지원하는 피직스입니다.
  • ClampingScrollPhysics: Android 스타일의 바운스 효과를 지원하지 않는 피직스입니다.
  • FixedExtentScrollPhysics: 길이가 고정된 child를 가지는 리스트 또는 그리드를 구현하는 데 사용할 수 있는 피직스입니다.
  • PageScrollPhysics: 페이지뷰에서 사용할 수 있는 피직스입니다.

 

 

ScrollDirection : 스크롤 방향을 정합니다.

  • Axis.vertical
  • Axis.horizontal

 

 

참고

https://medium.com/@roaakdm/flutter-scrollphysics-variations-use-cases-da87528cc6c1