[Flutter] 원하는 위치로 스크롤하기

CHOI·2021년 12월 19일
2
post-thumbnail

scroll to index

scroll to index는 리스트 목록 중에서 정확한 어느 지점으로 이동하고 싶을 때 사용하면 좋은 패키지입니다.

일반 리스트에서 원하는 지점으로 이동을 하고 싶을 때는 정확한 좌표. 즉, offset을 지정을 해줘야지만 이동을 하는데 리스트 목록들의 높이, 혹은 길이가 다 각각 다를 경우 offset을 알 경우가 힘듭니다.

쉬운 방법으로 index만으로 리스트를 이동하고 싶을 경우 사용하기 좋습니다.

1. 초기 세팅

리스트 위젯 안에 어떠한 목록들을 넣어줄 것인지 알아야 하기 때문에 리스트 목록을 우선 생성해 줍니다.
또한 리스트를 스크롤을 하기 위한 scroll controller도 생성을 해줍니다.

// scroll controller.
final AutoScrollController _controller = AutoScrollController();

// list.
static const List<Color> _list = Colors.primaries;

2. list widget 생성

리스트 목록을 생성을 해주었으면, 목록을 출력시키기 위한 위젯을 생성해 줍니다.
저는 리스트 목록의 높이가 다르더라도 index 만으로 이동 가능한 것을 보여주기 위해서 높이를 랜덤 값으로 지정해 주었습니다.

ListView.builder(
  itemCount: _list.length,
  controller: _controller,
  padding: EdgeInsets.zero,
  itemBuilder: (context, index) {
    final int _random = Random().nextInt(7);
    final double _randomHeight = 100.0 * _random;
      return Container(
        width: double.infinity,
        height: _randomHeight,
        color: _list.elementAt(index),
        child: Center(
          child: Text(
            'index: $index\nheight: ${_randomHeight.round()}',
        ),
      ),
    );
  },
),

3. AutoScrollTag

리스트 목록을 AutoScrollTag 위젯으로 감싸면 scroll to index를 이용 준비는 끝납니다.
AutoScrollTag은 key, controller, index 값이 필수 값으로 지정돼있습니다.

AutoScrollTag(
  key: ValueKey(index),
  controller: _controller,
  index: index,
  child: Container(
    width: double.infinity,
    height: _randomHeight,
    color: _list.elementAt(index),
    child: Center(
      child: Text(
        'index: $index\nheight: ${_randomHeight.round()}',
      ),
    ),
  ),
)
AutoScrollTag({
  required Key key,
  required this.controller,
  required this.index,
  this.child,
  this.builder,
  this.color,
  this.highlightColor,
  this.disabled: false
}) : assert(child != null || builder != null), super(key: key);



4. 리스트 스크롤

리스트를 스크롤 하기 위해서는 contollerindex, duration, preferPosition이 필요로 합니다.
scroll to index는 index를 통한 스크롤 이외에도 다양한 이동방식을 지원하고 있습니다.

floatingActionButton: FloatingActionButton(
  onPressed: () async {
    _controller.scrollToIndex(
      5,
      duration: const Duration(milliseconds: 500),
      preferPosition: AutoScrollPosition.begin,
    );
  },
  child: const Icon(
    Icons.swap_vert_outlined,
  ),
)

AutoScrollPosition
AutoScrollPosition은 위젯의 시작지점에 스크롤할지, 중간에 할지, 끝 지점에 할지 정하는 위치값입니다.

enum AutoScrollPosition { begin, middle, end }

AutoScrollController의 이동방식

_controller.jumpTo(value);
_controller.scrollToIndex(index);
_controller.animateTo(offset, duration: duration, curve: curve);

전체 코드

import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:scroll_to_index/scroll_to_index.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  late AutoScrollController _controller;

  // list.
  static const List<Color> _list = Colors.primaries;

  
  void initState() {
    super.initState();
    _controller = AutoScrollController();
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          _controller.scrollToIndex(
            5,
            duration: const Duration(milliseconds: 500),
            preferPosition: AutoScrollPosition.begin,
          );
        },
        child: const Icon(
          Icons.swap_vert_outlined,
        ),
      ),
      body: ListView.builder(
        itemCount: _list.length,
        controller: _controller,
        padding: EdgeInsets.zero,
        itemBuilder: (context, index) {
          final int _random = Random().nextInt(7);
          final double _randomHeight = 100.0 * _random;
          return AutoScrollTag(
            key: ValueKey(index),
            controller: _controller,
            index: index,
            child: Container(
              width: double.infinity,
              height: _randomHeight,
              color: _list.elementAt(index),
              child: Center(
                child: Text(
                  'index: $index\nheight: ${_randomHeight.round()}',
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

참고 자료

flutter package - scroll_to_index

profile
Mobile App Developer

0개의 댓글