FlutterではさまざまなUIを実装するためめに、多くのパーツが用意されています。それらの実装方法や機能を理解するためには、実際にアプリを作りながら学んでいくのが効果的です。
今回は、Flutterでカウンターアプリを作りながらUIの仕組みを紹介していきます。
Flutterの基本的な構造
Flutterでは、HTMLやReactのようにUIでUIを囲んでいくような書き方をしていきます。UIを囲うためにはWidgetというクラスを利用します。今回は、StatelessWidgetというWidgetを使ったサンプルを使って紹介します。
Flutter UIの基本知識
まずは、Flutterアプリの開発を理解する上で基本となる知識を解説します。
Widgetとは
Widgetとは、画面のベースとなる基底Widgetとボタンやテキストといった細かいUIになるWidgetなど、さまざまなWidgetが存在しています。FlutterアプリはこのWidgetというパーツを組み合わせてアプリUIを作っていきます。
Stateとは
Stateとは、Widgetの状態や変化を記録・保持するための機能です。フォロー・未フォローや会員・未会員といったステータスによって、UIの表示を切り替えたい時などに、それらの情報をStateに保持しておくことによってWidgetの表示を切り替えたりします。
「State
ベースとなる2種類のWidget
Flutterでよく使われるベースとなる2種類のWidgetがあります。
- StatelessWidget
- StatefulWidget
まずはこの2つのWidgetの理解が必要なので、簡単に解説していきます。
StatelessWidgetとは
Stateを持たない基底Widgetの一つです。Widgetが生成されたときや、親Widgetのステータスが変更された時など自身のWidget以外の変化があった場合にWidgetが生成されます。
StatefulWidgetはStateを管理できるWidget
ドキュメントには、以下のように書いてあります。
The logic and internal state for a StatefulWidget.
直訳すると、Stateを保持することができる基底Widgetの一つであることを示しています。「StatefulWidgetでは、Stateを使って状態管理できるようしたWidgetを使うよ!」ということになります。
StateをWidget内に保持するので、Stateに保存されている値によって内部にもつWidgetの表示を切り替えることができます。 setStateが呼ばれるたびに、Widgetが生成されるようになっています。
StatelessWidgetとの違いは、Stateを保持することができるかできないかという点です。
サンプルアプリで使われているWidget
ここからは、サンプルアプリで使われているWidgetについて紹介していきます。
Scaffold
アプリの基本構造となるナビゲーションやコンテンツ部分などをレイアウトしてくれるWidgetです。このWidgetに、ナビゲーションやコンテンツ部分のWidgetを当てはめることでアプリの全体的なUIを自動で構成してくれます。
AppBar
アプリのヘッダーになるWidgetです。AppBarは現在のスクリーンに関連するコンテンツやアクションを提供するためのものです。画面のタイトルやナビゲーションといったものです。Scaffoldのappbar要素に設定することでヘッダー表示が可能になります。
AppBar( title: Text(widget.title), )
FloatingActionButton
アプリの右下に少し浮いた形で表示されるボタンWidgetです。ツイッターのアプリでツイートする際に使うボタンですね。その画面で最も重要でメインとなる機能を提供してくれるボタンです。
FloatingActionButton(
onPressed: _add,
tooltip: 'Add',
child: const Icon(Icons.add),
)
Text
アプリ内でテキストを表示するためのWidgetです。ツイッターアプリでは、ユーザー名や投稿の文言などを表示するために利用しています。今回は、増減したカウントを表示するために利用しています。
Text("This is text widget")
Center
TextやBottonといったWidgetを中央に配置するために利用するWidgetです。Widgetを中央に配置ときに利用します。
Center(child: const Text("Text widget is placed center."))
Column
Widgetを縦に並べるために利用するWidgetです。このアプリでは、TextとButtonを縦に並べるために利用しています。この他にも、Rowという横に並べるためのWidgetもよく使うので覚えておくのをお勧めします。
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Line text A"),
const Text("Line text B"),
ResetButton(callback: _callback),
]
)
リセットボタンを設定してみよう
既に用意されているサンプルアプリに、カウントアップした数字を0にリセットするボタンを追加してみます。
リセットボタンを作る
数字を0にするために必要なボタンを用意します。このボタンを押すことで、中央に表示されている数字を0にします。このボタンにはリセット処理を実装せずに、プラスアイコンを設定したボタンとしてUI定義します。
class ResetButton extends ElevatedButton {
const ResetButton({Key? key, required VoidCallback? callback})
: super(key: key,
onPressed: callback,
child: const Text(
"Reset"
)
);
}
リセット処理を実装する
_incrementCounterの下の部分に_counterを0にリセットする処理を追加します。
void _resetCounter() {
setState(() {
_counter = 0;
});
}
配置する
リセット処理を実装したら、Scaffoldクラスのbody部分にあるColumnの末尾にリセットボタン追加します。その際に、先ほど実装したリセット処理をリセットボタンにセットします。
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
ResetButton(callback: _incrementCounter),
],
),
),
動作を確認する
実装が終わったらアプリをビルドして、実行してみましょう。すると、Resetというボタンが追加されているかと思います。
プラスボタンを何回かタップして中央の数字をカウントアップさせた後、リセットボタンを押してみましょう。すると、中央の数字が0にリセットされるようになっています。