Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
42
Help us understand the problem. What is going on with this article?
@najeira

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

More than 3 years have 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;
    }
  }
}

出来ました。

42
Help us understand the problem. What is going on with this article?
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
najeira
Software developer。Google Cloud(特にApp Engine)とFlutterのGoogle Developers Expert。好きな言語はGo。他Flutter/Dart, Android, iOS, Python。
michael-inc
マイケルはコミュニティサービスをつくる会社、「Community Builder」です。インターネットを通して人生がより豊かになるよう、人がつながる場所をつくりつづけます。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
42
Help us understand the problem. What is going on with this article?