Help us understand the problem. What is going on with this article?

Flutter の ListView / GridView で無限リストビュー

More than 1 year has passed since last update.

Flutter の ListView / GridView でいわゆる「無限リストビュー」を実装する方法を紹介します。アイテムを表示しつつ、末尾に到達したら次のアイテムを読み込んでいくやつです。

ListView / GridView には itemBuilder を受け取るコンストラクタがあります。

new ListView.builder(
  itemBuilder: (BuildContext context, int index) {
    // ここで index に応じた Widget を返す
    return new Text(index.toString());
  }
),

itemBuilder を使う場合は null を返したらリストビューの末尾であることを意味します。

つまり、以下のようにすることで、無限リストビューになります。

  • 要素があるうちは Widget を返す
  • 要素がなくなったら、次のアイテムを読み込む
  • 新しくアイテムを読み込んだら、setState で build させる

よって、おおよそ以下のような感じになります。

itemBuilder: (BuildContext context, int index) {
  // List<String> items; というプロパティがあるとして
  var length = items?.length ?? 0;

  if (index == length) {
    // アイテム数を超えたので次のページを読み込む
    _load();

    // 画面にはローディング表示しておく
    return new Center(
      child: new Container(
        margin: const EdgeInsets.only(top: 8.0),
        width: 32.0,
        height: 32.0,
        child: const CircularProgressIndicator(),
      ),
    );
  } else if (index > length) {
    // ローディング表示より先は無し
    return null;
  }

  // アイテムがあるので返す
  return new Text(items[index]);
},

以下、コード全体。サンプルとして、GitHub の flutter/flutter の Issues をリスト表示しています。

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';

import 'package:http/http.dart' as http;

void main() {
  runApp(new MaterialApp(
    home: new FooPage(),
  ));
}

class FooPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new FooPageState();
  }
}

class FooPageState extends State<FooPage> {
  int page = 1;

  List<String> issues;

  bool loading = false;

  @override
  Widget build(BuildContext context) {
    var length = issues?.length ?? 0;
    return new Scaffold(
      appBar: new AppBar(title: new Text("Infinite")),
      body: new ListView.builder(
        itemBuilder: (BuildContext context, int index) {
          if (index == length) {
            // アイテム数を超えたので次のページを読み込む
            _load();

            // 画面にはローディング表示しておく
            return new Center(
              child: new Container(
                margin: const EdgeInsets.only(top: 8.0),
                width: 32.0,
                height: 32.0,
                child: const CircularProgressIndicator(),
              ),
            );
          } else if (index > length) {
            // ローディング表示より先は無し
            return null;
          }

          // アイテムがあるので返す
          var title = issues[index];
          return new Container(
            decoration: new BoxDecoration(
              border: new Border(
                bottom: new BorderSide(color: Colors.grey.shade300),
              ),
            ),
            child: new ListTile(
              key: new ValueKey<String>(title),
              title: new Text(title),
            ),
          );
        },
      ),
    );
  }

  Future<void> _load() async {
    if (loading) {
      return null;
    }
    loading = true;
    try {
      var url = "https://api.github.com/repositories/31792824/issues?page=${page}";
      var resp = await http.get(url);
      var data = json.decode(resp.body);
      setState(() {
        page += 1;
        if (data is List) {
          if (issues == null) {
            issues = <String>[];
          }
          data.forEach((dynamic elem) {
            if (elem is Map) {
              issues.add(elem['title'] as String);
            }
          });
        }
      });
    } finally {
      loading = false;
    }
  }
}

出来ました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした