皆さんが普段使っているアプリでも文字が上から順にリスト状に並んでいてスクロールできるみたいな処理結構使われてると思います。
代表例がTwitterですね。
他のユーザーが投稿した内容が上からタイル状に積み重なってスクロールすることで更に下の投稿が見られるといった、Twitterのタイムライン的な処理がListViewを使うと簡単に実装出来てしまいます。
言い換えると色々なWidgetを並べることができて、表示範囲を超えてもスクロールして画面に表示することができるWidgetです。
Widgetについてはこの記事で紹介しているので読んでみてください。
【Flutter】UI構築する際の基本Widgetついて解説!【サンプルコードあり】
今回はそんなアプリ作る時の基本になるListViewについて使い方などを紹介してみようと思います。
目次
ListViewの使い方
ListViewの使い方には大きく分けて以下の2つがあります。それぞれサンプルコードを載せながら紹介していこうと思います。
- 手動でリストを作る
- 自動でリストを作る
手動でリストを作る
手動でリストを作ると言うのは、自分で表示したいリストの数だけWidgetを設置していく方法です。
僕の場合だと表示したいWidget1つ1つで適応したい色や大きさなどが違うなどの事情がある時に使うイメージですね。
処理が軽くなる
単純にコードにしてあるWidgetをそのまま出力すればいいだけなので、無駄なロジックが実装されていない分動作は軽いです。
コードの可読性が悪くなる
自分で一つ一つWidgetを積み重ねて行くので、その分コードの文量が増えてプログラム全体の可読性が悪くなります。
特にDartという言語の仕様上Widgetを作るに連れて「()」や「{}」、「 [] 」が多くなりますし、
例えば全てのWidgetにText Widgetを使うとしたらTestStyleを指定して文字サイズや色、フォントなどを設定すると思いますが手動でリストを作るとなるとそれも個別に記載しないとならないのでやっぱりかさばります。
サンプルコード
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'スクショ!',
),
),
body: Center(
// -*-*-*-*-*-*-*-*- ListView使ってるとこ -*-*-*-*-*-*-*-*-
child: ListView(
//scrollDirection: Axis.horizontal, // 横
padding: EdgeInsets.all(36.0),
shrinkWrap: true,
children: [
Container(
color: Colors.red,
child: Text(
"ジョナサン・ジョースター",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25.0),
),
),
Container(
color: Colors.green,
child: Text(
"ジョセフ・ジョースター",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25.0),
),
),
Container(
color: Colors.blue,
child: Text(
"空条承太郎",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25.0),
),
),
],
),
// -*-*-*-*-*-*-*-*- ListView使ってるとこ -*-*-*-*-*-*-*-*-
),
);
}
}
例として、3人のジョジョをリストにするだけでこんだけ行数が必要になってしまいます。
リスト個々で別に背景色を変えたりなどのプロパティを設定できるのはメリットだと思いますが、表示したいリストの数が多くなってくると、その分比例してコード記述量が増えてくるので、今世に出てるジョジョ全員を紹介しようと思ったらどんだけコードが長くなるのかは想像したくないです。
自動でリストをつくる
自動でリストを作成するには、「ListView.builder」を使います。
というか、そもそもリストを使いたい時は何か多くを一覧にして表示したい時がほとんどだと思うのでこっちの方法を使う人がほとんどだと思います。
僕もリストを作るとなったらほぼListView.builderを使ってますね。
Widgetそれぞれにプロパティを適用する必要がない、あるいは表示するWidget全てに同じプロパティを適用して表示するのであれば、この方法で実装した方がコードがすっきりして幸せになれます。
自動でリストをつくる
手動で作る時とは反対に、一つテンプレートになるWidgetを繰り返し処理して表示することでその分全体のコード量を抑える事ができます。
Widget別々にプロパティを設定できない
さっき少し触れましたが、自動でリストを作成するとテンプレートにしたWidgetをもとにして繰り返し処理で画面に表示するので、表示されたWidgetそれぞれに独自のプロパティを設定することができません。
例えばリスト毎に文字色を変えたい、フォントを変えたいみたいな時には向かないので、そのような時は手動でリストを作った方がいいと思います。
サンプルコード
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 表示したいリスト
List jojo = [
'ジョナサン・ジョースター',
'ジョセフ・ジョースター',
'空条承太郎',
'東方仗助',
'ジョルノ・ジョバァーナ',
'空条徐倫',
'ジョニィ・ジョースター',
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'スクショ!',
),
),
body: Center(
// -*-*-*-*-*-*-*-*- ListView.builder使ってるとこ -*-*-*-*-*-*-*-*-
child: ListView.builder(
padding: EdgeInsets.all(36.0),
shrinkWrap: true,
itemCount: jojo.length,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.green,
child: Text(
jojo[index],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25.0),
),
);
},
),
// -*-*-*-*-*-*-*-*- ListView.builder使ってるとこ -*-*-*-*-*-*-*-*-
),
);
}
}
どうでしょう。これなら8部までのジョジョ全員をリスト表示してもコードがスッキリ見やすいですね。背景色は全て緑になっています。
ListView.builderのコードをざっくりと解説すると、
itemCount: jojo.length,
ここのコードで配列jojoに格納されている要素数をカウントしています。
今回で言えば配列jojoに要素は8つ格納されているので、最大インデックス番号の「7」が登録されています。
itemBuilder: (BuildContext context, int index) {
...
},
ここでitemBuilderを指定しています。このitemBuilderで囲まれた部分は先程のitemCountにカウントされた回数だけ繰り返しビルドすることができます。
今回配列jojoには8つの要素を格納してあるので8回ビルドが繰り返しされて「return Container」内のTextが8つ作成されることになります。
そしてitemBuilderの第二引数の「index」には現在繰り返されている回数の数字が格納されます。
return Container(
color: Colors.green,
child: Text(
jojo[index], // インデックス番号に対応した要素がテキストに反映される
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25.0),
),
);
その結果順番にText Widget内の「jojo[index]」で配列のインデックス番号に対応した要素があてはめられていって、配列内の要素全てが表示されるみたいな感じです。
よく使うプロパティ
scrollDirection
リストの並ぶ方向を決めることができます。
Axis.vertical
縦方向にリストを並べます。
デフォルトではこの設定になっているので縦がいい人はわざわざ指定する必要はありません。
Axis.horizontal
横方向にリストを並べます。
child: ListView(
scrollDirection: Axis.horizontal,
...
)
padding
ListViewの全体周りの間隔の幅を指定できます。
もし、ListViewの要素と要素の間に間隔を入れたい場合はContainer Widgetで囲んでそっちでpaddingプロパティを設定しましょう。
child: ListView(
padding: EdgeInsets.all(30.0),
...
)
shrinkWrap
TrueかFalseを指定することでListViewの大きさを自動で調節するかしないかを選択できます。
デフォルトではFalseになっています。
ListView関係でエラーがおきた時はこのプロパティをTrueにすると解決するかもしれません。
child: ListView(
shrinkWrap: true,
...
)
おわりに
こんな感じで僕自身ListViewはアプリ開発しててよく使うので備忘録としてまとめてみました。
少しでも参考になれば嬉しいです。
間違いなどあればコメントいただけると助かります。
Flutterの基本を体系的に学習したい方はこちらの書籍がおすすめです!
あと初心者向けにFlutterアプリの開発記事も書いているのでよければ読んでみてください!
【Flutter初心者向け】ルーレットアプリを作って今晩の夕食を決めてみた【ソースコピペOK】【Flutter/アプリ開発】スクレイピングを利用して副業案件検索アプリを作ってみよう!