今回はListViewウィジェットを利用し、スクロールすると無限に文字列が湧き出てくるアプリを作ってみます。
前回の記事で学んだStatefulWidget
を使って進めますので、StatefulWidgetについて詳しく学びたい方はこちらも参考にしてみてください。
※今回のアプリはFlutter公式サイトのチュートリアルを参考にしています
サンプルアプリを作ってみる
アプリの概要
次のステップでアプリを作ってみます。
- ランダム文字列を生成するライブラリをインストール
- StatefulWidgetを継承したRandomWordsクラスを作成する
- ランダム文字列を生成・表示する_buildSuggestionsメソッドを追加
実装
文字列生成用のライブラリをインストール
はじめにランダム文字列を生成するenglish_words
をインストールします。
# pubspec.yamlに追記
dependencies:
flutter:
sdk: flutter
english_words: ^3.1.5 # 追記
// main.dartに追記
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart'; // 追記
RandomWordsクラスを作成
次にランダム文字列のリストを表示するWidget、RandomWords
クラスを作るためにStatefulWidgetの雛形を作成します。
class RandomWords extends StatefulWidget {
@override
_RandomWordsState createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
@override
Widget build(BuildContext context) {
return Container();
}
}
生成した文字列を格納するリスト_suggestions
とフォントサイズの定義した_biggerFont
変数を予め用意しておきます。
class _RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _biggerFont = TextStyle(fontSize: 18.0);
@override
// ・・・
}
ランダム文字列を生成・表示する_buildSuggestionsメソッドを追加
次にListView
ウィジェットでランダム文字列のリストを表示する_buildSuggestions()
メソッドを追加します。
Widget _buildSuggestions() {
return ListView.builder(
padding: EdgeInsets.all(16.0),
itemBuilder: (context, i) {
if (i.isOdd) return Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll((generateWordPairs().take(10)));
}
return _buildRow(_suggestions[index]);
});
}
※この状態ではThe method ‘_buildRow’ isn’t defined for the class ‘_RandomWordsState’.とエラーが表示します
ListViewは無名関数として指定されたファクトリービルダー及びコールバック関数であるビルダープロパティitemBuilder
を提供します。
無名関数には2つのパラメータ、BuildContextであるcontext
と行のイテレータi
が渡されます。
ListView class – widgets library – Dart API
itemBuilderコールバックは、各行ごとに1回呼び出され、指定された要素がListTile
という行に配置されます。
今回のケースでは偶数行は、生成されたランダム文字列を、奇数行の場合は、分割ウィジェット(水平線)が追加され、視覚的に文字列を分離します。
各処理の詳細を見ていきましょう。
itemBuilderの1行目if (i.isOdd) return Divider();
はその行が奇数であるか判定し、奇数の場合はDivider
ウィジェットで水平線を返します。
Divider class – material library – Dart API
偶数業の場合は次のステップへ。
final index = i ~/ 2;
で水平線の数を差し引き、ランダム文字列の実際の数を算出しています。
さらに_suggetionsに格納されている数より大きくなった場合に、10個のランダム文字列を生成し追加します。
最後に_buildRow()
メソッドを呼び出し、新しいランダム文字列をListTileに配置します。
ListTileを返す_buildRowメソッドを_RandomWordStateに追加します。
Widget _buildRow(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
}
準備を整いましたので、仕上げです。
_RandomWordsStateクラスのbuild()を次のように更新します。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Infinity Scroll ListView'),
),
body: _buildSuggestions(),
);
}
最後にMyAppクラスを更新します。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Infinite Scroll ListView',
home: RandomWords(),
);
}
}
これで全ての実装が完了しました。
以下が完成したmain.dartの全文です。
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Infinite Scroll ListView',
home: RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
_RandomWordsState createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _biggerFont = TextStyle(fontSize: 18.0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Infinite Scroll ListView'),
),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return ListView.builder(
padding: EdgeInsets.all(16.0),
itemBuilder: (context, i) {
if (i.isOdd) return Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll((generateWordPairs().take(10)));
}
return _buildRow(_suggestions[index]);
});
}
Widget _buildRow(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
}
}
実行
作成したアプリを実行してみましょう。
スクロールするたびに生成されたランダム文字列が無限に湧き出てきたら成功です。