【Flutter】ListViewでデータ一覧を見やすく表示!

対象者

  • Flutterを学び始めたばかりの方、またはこれから学び始める方
  • ListViewなどのFlutterのウィジェットの使い方について理解を深めたい方
  • 自身のスキルセットを拡充し、新たなアプリ開発に挑戦したい方

はじめに

あなたがFlutterを学び始めているなら、きっと「リストの表示方法はどうすればいいのか?」という疑問にぶつかることでしょう。その答えはここにあります:ListViewです。FlutterのListViewを学ぶことは、アプリ開発のスキルを一段階引き上げるきっかけになるでしょう。この記事を通じて、ListViewの基本的な使い方から高度な使い方までを習得し、あなたのアプリ開発力を新たなレベルに引き上げてください。あなたがFlutterを使って何を作りたいかに関わらず、ListViewの知識はあなたのツールキットに必要不可欠なものとなるでしょう。

ListViewとは

ListViewとは、Flutterの主要なウィジェットの一つで、スクロール可能なリストを作成するためのものです。その最大の特徴は、一列に配置されたウィジェットのリストを作成し、それらをスクロールする機能があります。これは、長いリストを表示する際に特に役立ちます。

この特性は、ユーザーが自由にスクロールして情報を探すことができる現代のアプリのデザインにとって不可欠なものとなっています。これにより、ユーザーは一度に大量の情報を表示することなく、必要な情報を探すことができます。

また、ListViewはその柔軟性により注目されています。各項目は任意のウィジェットを取ることができるため、テキストだけでなく画像やアイコン、さらにはカスタムウィジェットまで表示することが可能です。

ListViewの基本形

ListViewの基本形は、明示的なリストからウィジェットのスクロール可能な配列を作成します。これは、小規模なリストに対して特に適しています。なぜなら、この形式ではリストの作成時にすべての子ウィジェットの生成が行われるため、子ウィジェットの数が多くなるとパフォーマンスに影響を及ぼす可能性があるからです。

基本形のListViewの使用は非常に直感的で、childrenパラメータに表示したいウィジェットのリストを渡すだけです。以下にその例を示します。

ListView(
  children: <Widget>[
    ListTile(
      leading: Icon(Icons.map),
      title: Text('Map'),
    ),
    ListTile(
      leading: Icon(Icons.photo_album),
      title: Text('Album'),
    ),
    ListTile(
      leading: Icon(Icons.phone),
      title: Text('Phone'),
    ),
  ],
)

このコードは、3つの項目を持つ基本的なリストを作成します。各項目はListTileウィジェットで構成され、アイコンとテキストを持つことができます。

それでは、指定された目次に基づいてブログ記事の一部を作成します。

ListViewの種類

FlutterのListViewウィジェットは非常に柔軟性があり、いくつかの異なる方法で利用できます。以下では、その主要な3つの形式、すなわち、ListView.builderListView.separated、そしてListView.customについて説明します。

ListView.builderの利用

ListView.builderは、大規模なリストや無限リストを扱う際に特に有用です。なぜなら、ListView.builderは必要に応じてウィジェットを動的に生成するため、メモリ使用量を削減し、パフォーマンスを向上させることができるからです。

ListView.builderの使用は簡単で、リストの各項目を生成するためのitemBuilder関数と、リストの項目数を指定するitemCountパラメータを提供するだけです。以下にその例を示します。

ListView.builder(
  itemCount: 100,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text('Item $index'),
    );
  },
)

このコードは、”Item 0″から”Item 99″までの100個の項目を持つリストを生成します。

ListView.separatedとListView.customの特徴

ListView.separatedは、リストの各項目の間に区切り線やスペースを簡単に挿入するためのウィジェットです。この区切り線は、separatorBuilder関数によって定義されます。これは、見た目を整えるために頻繁に使用されます。

一方、ListView.customは、最も柔軟なリストビューを提供します。これは、スライバブルや拡張可能なリストなど、特殊なリストを作成するために使用されます。

ListView.separatedとColumnの違い

ListView.separatedとColumnは、両方ともウィジェットのリストを表示するために使用されますが、その使用目的と特性は異なります。

ListView.separatedは、上で述べたように、各項目の間に区切り線を挿入することが可能です。また、スクロール可能であるため、項目数が多くても安心して利用できます。

一方、Columnウィジェットはスクロール機能を持たないため、すべての子ウィジェットが画面内に収まるように設計する必要があります。しかし、縦方向にウィジェットを配置するときには、シンプルで直感的です。

ListViewのスクロール方向の設定

ListViewウィジェットは、自然にスクロールが可能で、これはユーザー体験の観点から見て大きな利点となります。スクロール方向はデフォルトで垂直方向となりますが、水平方向へのスクロールも設定可能です。以下では、それぞれの設定方法を解説します。

垂直方向のスクロール

ListViewウィジェットのデフォルトのスクロール方向は垂直です。これはユーザーが通常スマートフォンを使うときの自然な操作性を考慮した結果で、特に設定をしなくてもリストは垂直方向にスクロールします。

垂直方向へスクロールするListViewの基本的な実装は以下のようになります。

ListView(
  children: <Widget>[
    ListTile(
      leading: Icon(Icons.map),
      title: Text('Map'),
    ),
    ListTile(
      leading: Icon(Icons.photo_album),
      title: Text('Album'),
    ),
    ListTile(
      leading: Icon(Icons.phone),
      title: Text('Phone'),
    ),
  ],
)

このコードは、アイコンとテキストを含む3つのリスト項目を垂直方向にスクロール可能な形で表示します。

水平方向のスクロール

一方、ListViewを水平方向にスクロールさせたい場合は、scrollDirectionプロパティをAxis.horizontalに設定します。これは特定のUIデザインや、画像ギャラリーなどの横に並ぶ要素を表示する場合に便利です。

水平方向へスクロールするListViewの実装例は以下の通りです。

ListView(
  scrollDirection: Axis.horizontal,
  children: <Widget>[
    Container(
      width: 160.0,
      color: Colors.red,
    ),
    Container(
      width: 160.0,
      color: Colors.blue,
    ),
    Container(
      width: 160.0,
      color: Colors.green,
    ),
    Container(
      width: 160.0,
      color: Colors.yellow,
    ),
    Container(
      width: 160.0,
      color: Colors.orange,
    ),
  ],
)

このコードは、色の異なる5つのコンテナを水平方向にスクロール可能な形で表示します。

以上が、ListViewのスクロール方向の設定方法についての解説です。適切なスクロール方向を設定することで、ユーザー体験を向上させることが可能です。

それでは、指定された内容に基づいて、ブログ記事の一部を作成します。

ListViewの実践的な利用例

ListViewはその汎用性から、多くの場面で使用されます。ここでは、小規模なリストと大規模なリストの作成方法を具体的に解説します。

小規模なリストの作成方法

小規模なリストの作成には、基本的なListViewの実装が適しています。数が少ない項目を一覧表示するために、childrenプロパティに直接ウィジェットをリストとして提供することができます。

小規模なリストの作成例を以下に示します。

ListView(
  children: <Widget>[
    ListTile(
      leading: Icon(Icons.map),
      title: Text('Map'),
    ),
    ListTile(
      leading: Icon(Icons.photo_album),
      title: Text('Album'),
    ),
    ListTile(
      leading: Icon(Icons.phone),
      title: Text('Phone'),
    ),
  ],
)

このコードでは、アイコンとテキストを含む3つの項目を持つリストを作成しています。

大規模なリストの作成方法

一方、大規模なリストの場合、ListView.builderを使用するのが適しています。ListView.builderは大量のデータを効率的に扱うために設計されており、一度に画面に表示される項目のみを描画します。これによりパフォーマンスを維持しながら大量の項目を扱うことができます。

大規模なリストの作成例を以下に示します。

final List<String> entries = <String>['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

ListView.builder(
  itemCount: entries.length,
  itemBuilder: (BuildContext context, int index) {
    return ListTile(
      title: Text('Entry ${entries[index]}'),
    );
  }
)

このコードでは、アルファベットのリストを生成し、それをListView.builderを使用してリストとして表示しています。

以上が、ListViewの小規模なリストと大規模なリストの作成方法についての解説です。適切な方法を選択することで、効率的にリストを作成することが可能です。

Q&A

Q: ListViewとListView.builderは何が違うのですか?

A: ListViewは直接ウィジェットのリストをchildrenプロパティに渡します。一方、ListView.builderは表示するウィジェットを動的に生成します。大規模なリストを表示する場合、ListView.builderを使用するとリソースを節約できます。

Q: ListViewで画像を表示するにはどうすればいいですか?

A: AssetImageやNetworkImageを使用してListView内に画像を表示することができます。これらはImageウィジェットと一緒に使用します。

Q: ListViewのスクロール方向を変更するにはどうすればいいですか?

A: ListViewのscrollDirectionプロパティを使用してスクロール方向を設定できます。デフォルトは垂直方向ですが、Axis.horizontalを指定することで水平方向にスクロールするように変更できます。

Q: 新たな要素が追加したときにスクロール位置がずれてるのはどうすれば良いですか

A: physics: const RangeMaintainingScrollPhysics()を設定してください。

まとめ

これまで学んだ内容を振り返り、ListViewについての理解を深めていきましょう。まず、ListViewはFlutterにおける最も一般的なスクロール可能なリストウィジェットであり、アプリケーションの多くの部分で使用できます。ListView.builderを使うと、大量のデータを表示しながらもリソースを節約することが可能です。また、AssetImageやNetworkImageを用いてリスト内に画像を表示することもできます。ListViewのスクロール方向はデフォルトで垂直ですが、水平方向にも設定できます。さらに、ListView.separatedやListView.customなど、さまざまな種類のListViewを試すことで、より多様な状況に対応する能力を身につけることができます。

参考

ソース(main.dartにコピペして動作確認用)

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ListView Sample',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView Sample'),
        ),
        body: ListView.builder(
          itemCount: 50,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('List Item $index'),
              subtitle: Text('This is the details of item $index'),
            );
          },
        ),
      ),
    );
  }
}