4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Flutter】任意の場所まで自動スクロール(前編)

Last updated at Posted at 2021-10-09

概要

Flutterで縦に長いページを作成する場合、任意の場所まで自動でスクロールさせたいユースケースがあると思います。
デフォルトSDKで一応用意されているもののListViewの位置指定をindex単位で指定できません。
今回はindex単位で遷移できる【scroll_to_index】の具体的な実装方法を整理したいと思います。

なお、【scroll_to_index】の弱点としては、indexを利用した遷移についてはanimationのみサポートしていることでしょうか(2021年10月時点)。
index単位でジャンプさせたい場合は、別のプラグイン採用をご検討いただければと思います。

スクロールについては、前後編を予定しています。

| 内容
---|---
前編(本記事)|【同一Widget内】で、任意のスクロール場所へ遷移する方法
後編|【表示と異なるWidget】で、任意のスクロール場所へ遷移する方法
※具体的にはAppBarを押すとページ最上部に遷移する(イメージ:Twitter, Instagramなど)

実装イメージ

output.gif

環境

$ flutter --version
Flutter 2.5.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision ffb2ecea52 (3 weeks ago) • 2021-09-17 15:26:33 -0400
Engine • revision b3af521a05
Tools • Dart 2.14.2

pubspec.yaml

dependencies:
  # ✨✨✨↓追加✨✨✨
  scroll_to_index: ^2.1.0

実装

こちらの記事を参考にしつつ、実際に組み込んでみました。
注意してほしい箇所はコメントに記載しているので、その辺りも見ていただければと。
GitHubにも全文公開しているのでご参考まで

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

  @override
  Widget build(BuildContext context) {
    final controller = AutoScrollController();

    return ListView.builder(
      controller: controller,

      /// とりあえず100個だけ表示するように実装
      itemCount: 100,
      itemBuilder: (context, index) {
        return AutoScrollTag(
          key: ValueKey(index),
          controller: controller,
          index: index,
          child: Column(
            children: [
              /// ListViewの先頭のみ、ボタンを設置する実装(ここは正直あんまり参考にしない方がいいかも?)。
              if (index == 0)
                SizedBox(
                  width: double.infinity,
                  child: ElevatedButton(
                    onPressed: () {
                      /// ボタンを押したら任意の場所にジャンプできる。50の値を適宜変更してください。
                      controller.scrollToIndex(
                        50,

                        /// beginがListのindexの頭に表示される。他に、middleとendが存在する
                        preferPosition: AutoScrollPosition.begin,
                      );
                    },
                    child: const Text('50番目にジャンプ'),
                  ),
                ),
              SizedBox(
                width: double.infinity,
                height: 80,

                /// 行頭に遷移されることがわかりやすいようにCardウィジェットを採用しています。適宜変更してください。
                child: Card(
                  child: Text(
                    '$index',
                    style: const TextStyle(fontSize: 24),
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

そこまで長くないので呼び出し元のサンプルコードも掲載します。

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Sample of Scroll to Jump'),
        ),

        /// 呼び出し元のメソッド
        body: const ScrollWidget(),
      ),
    );
  }
}
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?