2
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-11-13

Flutterでスクロールバーを表示させたい場合、いくつか選択肢がある。が、「常にスクロールバーを表示させたい」なーと思ってScrollBarisAlwaysShown: trueを設定すると、なぜか途端にエラーの山にのまれて大変なことになるので、迷わないように定型化してみた。

結論

final _scrollController = ScrollController(); // ScrollControllerは必須

// 中略

Scrollbar(
  isAlwaysShown: true,
  controller: _scrollController, // <- 同じScrollControllerを配置

  child: SingleChildScrollView(
    controller: _scrollController, // <- 同じScrollControllerを配置
    
    // 以下、ScrollView内に配置したいWidget
    child: ListView( 
      // ListViewを配置する場合、以下2行は必須
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      children: [
        // ...
      ]
    )

  )
)

実際の動作は以下のDartPadで確認できる。
https://dartpad.dartlang.org/?id=d1330072fc1e7f2b9c9af52a1bd87edf&null_safety=true

解説

特にListViewと併用する場合などに詰まってしまうパターンがよくあると思うので、まとめてテンプレ化した。

解説は以下参考ページに詳しく書かれているので割愛。isAlwaysShown: true する場合もしない場合も、このテンプレを基本にしておくと役立つと思うので、まとめてWrapしたWidgetにしておくと便利かもしれない。

同じページに複数のスクロール画面がある場合は、もちろん各場所でScrollControllerは分ける必要があるけれど、その場合もScrollbarSingleChildScrollViewでは共通のScrollControllerが必要。

カスタムWidgetにまとめる

ということで、こんな感じにWidget化しておくと使いやすい。使うときはSimpleScrollViewあるいはScrollListViewを呼べばよいので迷いがない。

import 'package:flutter/material.dart';

void main() => runApp(App());

class SimpleScrollView extends StatelessWidget {
  SimpleScrollView({required this.child, this.isAlwaysShown = true});

  final Widget child;
  final bool isAlwaysShown;

  final _scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
        isAlwaysShown: isAlwaysShown,
        controller: _scrollController,
        child: SingleChildScrollView(
          controller: _scrollController,
          child: child,
        ));
  }
}

class ScrollListView extends StatelessWidget {
  ScrollListView({required this.children});

  final List<Widget> children;

  @override
  Widget build(BuildContext context) {
    return SimpleScrollView(
        child: ListView(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            children: children));
  }
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Material(
      child: Scaffold(
        body: ScrollListView(children: [
          for (var i = 0; i < 50; i += 1) ListTile(title: Text("Item $i"))
        ]),
      ),
    ));
  }
}

DartPad
https://dartpad.dartlang.org/?id=bbd86b3e8515a4559255238b7588bf95&null_safety=true

参考

2
1
1

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
2
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?