さくっとリスト一覧を実装したいときに使える無限スクロール(Infinity Scroll)パターン【Flutter / Riverpod】
この記事では、私が Flutter で無限スクロールを実装する時によく使う方法をご紹介します。無限スクロールを実装する方法は、1つではなく他にも色々ありますが、ここで紹介する方法はその中でもコード量が少ないので(ScrollController を使わないため)ぱぱっとやりたい時におすすめです。
もし ScrollController が他の用途で必要な場合には、素直に ScrollController を使ってしまった方がいいと思います。
今回の実装には Riverpod を使っていますが、もちろん他の方法でも OK です。Riverpod については、こちらをご覧ください。
説明のために実際には API 呼び出しをする部分で、Future で待って文字列の item を追加していく仮の実装をしました。コードは動きます。
最低限実現したいことは以下です
・初期ロード時にローディングアイコンを表示する
・リストの下まで行ったら表示する
・追加ロード時に一番下にローディングアイコンを表示する
・これ以上ロードできない時はローディングアイコンは表示しない
見た目の部分はこちらです:
class InifinityScrollSample extends HookWidget {
@override
Widget build(BuildContext context) {
final List<String> items = useProvider(itemsProvider).state;
return MaterialApp(
home: Scaffold(
body: ListView.builder(
itemCount: context.read(itemController).listLength,
itemBuilder: (context, int index) {
if (index < (items?.length ?? 0)) {
return Text(items[index]);
}
context.read(itemController).loadItemsIfNeeded();
return const LinearProgressIndicator();
},
),
),
);
}
}
見た目部分のポイント
・index がリストの長さをこえない時のみ Item にアクセスする
・index がリストの長さをこえた時には新しいアイテムをロードする(同時に、ローディングアイコンを返却する)
ロジックはこちら:
final itemsProvider = StateProvider<List<String>>((ref) => null);
final itemController =
Provider<ItemController>((ref) => ItemController(ref.read));
class ItemController {
final Reader _read;
ItemController(this._read);
bool _isLoading = false;
bool _hitTheBottom = false;
List<String> get _items => _read(itemsProvider).state;
int get listLength => (_items?.length ?? 0) + (_hitTheBottom ? 0 : 1);
Future<void> loadItemsIfNeeded() async {
if (_isLoading || _hitTheBottom) {
return;
}
_isLoading = true;
await Future.delayed(const Duration(seconds: 1));
_read(itemsProvider).state = [
...(_items ?? []),
'Item ${_items?.length ?? 0}',
'Item ${(_items?.length ?? 0) + 1}'
];
_isLoading = false;
if (10 <= _items.length) {
_hitTheBottom = true;
}
}
}
ロジック部分のポイント
・hitTheBottom によってリストの長さを変更する(まだ一番下に来ていない時はリストを長くする)
・ローディング中の時や一番下に来たときは何もしない
・items の初期値が null なのは、まだロードしていないから空なのか、ロードしたけど空なのかを判定するため
全コードはこちらです:
インフィニティスクロールのやり方は、他にも、色々あります:
@heavenosk さん
- https://qiita.com/heavenosk/items/30e9769fcfde5f0fc096
@kikuchyさん
- https://qiita.com/kikuchy/items/07d10394a4f7aa2a3836
ご覧いただきありがとうございました。