[flutter] 스크롤 시 플러터 그리드뷰에서 sticky 머리글 만들기

플러터(Flutter) 앱에서 그리드뷰(GridView)를 사용하여 아이템을 표시하는 동안 스크롤을 할 때 스티키(sticky)한 머리글을 만들고 싶다면 어떻게 해야 할까요? 이 기능은 사용자가 그리드뷰를 스크롤할 때 항상 상위에 머무르는 헤더를 추가해주는데 유용합니다.

1. 스티키 그리드뷰 위젯 생성

스티키 그리드뷰를 만들기 위해 SliverAppBar 위젯을 사용할 것입니다. 이 위젯은 그리드뷰의 헤더 역할을 하며 항상 상단에 고정됩니다.

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      pinned: true,
      title: Text('Sticky Header'), // 헤더에 표시할 제목
    ),
    SliverGrid.count(
      crossAxisCount: 2,
      children: <Widget>[
        // 그리드뷰에 표시할 아이템 위젯들
        // ...
      ],
    ),
  ],
)

CustomScrollView는 스크롤 가능한 위젯이며 SliverAppBarSliverGrid.count 위젯으로 구성됩니다. SliverAppBarpinned 속성을 true로 설정하여 헤더를 항상 상단에 고정시킬 수 있습니다.

또한, SliverGrid.count 위젯을 사용하여 그리드뷰를 생성하고 원하는 아이템 위젯들을 추가할 수 있습니다.

2. 스크롤 이벤트 처리

그리드뷰를 스크롤하는 시점에 따라 헤더를 보이거나 숨기기 위해 ScrollController를 사용할 것입니다.

먼저, ScrollController를 추가하고 그리드뷰의 스크롤 위치를 탐지하기 위한 addListener 메소드를 등록할 수 있습니다.

ScrollController _scrollController = ScrollController();

@override
void initState() {
  super.initState();
  _scrollController.addListener(_scrollListener);
}

void _scrollListener() {
  if (_scrollController.offset > 0) {
    // 아래로 스크롤하는 경우
    setState(() {
      _isSticky = false; // 헤더를 숨김
    });
  } else {
    // 위로 스크롤하는 경우
    setState(() {
      _isSticky = true; // 헤더를 보임
    });
  }
}

_scrollListener 메소드에서는 현재 스크롤 위치를 확인하고 _isSticky 값을 변경하여 헤더의 표시 여부를 조절합니다. 스크롤 위치가 0인 경우에는 위로 스크롤하고 있으므로 헤더를 보여주며, 그 외에는 헤더를 숨깁니다.

3. 위젯에 헤더 표시

위에서 생성한 스티키 그리드뷰와 스크롤 이벤트 처리를 위한 ScrollController를 사용하여 헤더를 화면에 표시할 수 있습니다.

Stack(
  children: <Widget>[
    // 그리드뷰
    CustomScrollView(
      controller: _scrollController,
      slivers: <Widget>[
        SliverAppBar(
          pinned: true,
          title: Text('Sticky Header'), // 헤더에 표시할 제목
        ),
        SliverGrid.count(
          crossAxisCount: 2,
          children: <Widget>[
            // 그리드뷰에 표시할 아이템 위젯들
            // ...
          ],
        ),
      ],
    ),
    // 헤더
    Visibility(
      visible: _isSticky, // _isSticky 값에 따라 표시 여부 결정
      child: Container(
        height: 50,
        color: Colors.white,
        child: Center(
          child: Text(
            'Sticky Header',
            style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 18,
            ),
          ),
        ),
      ),
    ),
  ],
)

Stack 위젯을 사용하여 그리드뷰와 헤더를 겹쳐서 표시할 수 있습니다. Visibility 위젯을 사용하여 _isSticky 값에 따라 헤더를 표시하거나 숨길 수 있습니다. _isSticky 값이 true인 경우에는 헤더를 보여주고, false인 경우에는 숨깁니다.

위의 예제 코드는 스크롤 시 플러터 그리드뷰에서 스티키 머리글을 만드는 방법을 보여줍니다. 이 방법을 사용하여 앱에서 스티키 헤더 기능을 구현할 수 있습니다.

참고 자료