目次
概要
Flutterを使ってアプリを開発してみようかと思います。今回のブログポストではFlutterの基本要素であるウィジェットに関して説明します。
このブログポストで紹介したソースコードは下記のリンクで確認することができます。
ウィジェット
Flutterはウィジェットで始まってウィジェットでお終わります。Flutterで画面に表示される全ての要素がウィジェットで、目に見えないけど画面の構造であるレイアウト(Layout)もウィジェットです。
したがってFlutterでアプリを開発するためにはウィジェットを理解する必要があります。
ウィジェットは大きく二つで分類されております。
- Stateful Widget
- Stateless Widget
それじゃ、各ウィジェットを詳しく見て見ましょう。
Stateful Widget
FlutterでStateful Widget
はどのような状態の値を持っており、その状態の値による画面の動きや変化を表現する時使います。
- 例:テキストフィールド、ボタン、サーバからもらったデータを表示するウィジェットなど
上のようにStateful Widgetはユーザとのインタラクションによって模様や形が変わる時使います。Stateful WidgetはStatefulWidget
を継承して生成します。
Stateless Widget
Stateless Widget
はStateful Widgetとは違って、どんな状態も持ってない静的なウィジェットです。どんな状態の値も持ってないので、Stateless Widgetは画面上でどんな動きも変化もありません。
- 例:テキスト、イメージなど
上のようにStateless Widgetは画面には表示されるが、ユーザとはどんなインタラクションもしなくて、どんな動きや変化もしないです。Stateless WidgetはStatelessWidget
を継承して生成します。
Widget tree
基本的にはFlutterはウィジェットを使って開発をします。一つのウィジェットは複数のウィジェットを含むことができますし、全てのウィジェットは親子関係を持ってます。このように親子関係を持ってると、これをTree
構造で表現や管理することができます。
例えば、HTMLがウェブブラウザに表示される時、ブラウザはHTMLの要素をDOMツーリを生成して管理してます。これと同じようにFlutterは全てのウィジェットをWidgetツーリを生成して管理します。
全てのウィジェットは親ウィジェットと子ウィジェットで構成されて、親のウィジェットはParent Widget
またはWidget Container
と呼ばれます。
コーディング
それじゃ、今から簡単にコーディングをしてウィジェットを理解してみましょう。
Stateless widget コーディング
Stateless widgetを理解するため、次のコマンドを実行してFlutterプロジェクトを生成します。
flutter create stateless_widget
そして次のコマンドを使ってVSCodeを実行します。
cd stateless_widget
code .
VSCodeが立ち上がったら、lib/main.dart
ファイルを開いて次のように修正します。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeWidget(),
);
}
}
class HomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stateless Widget'),
),
body: Center(
child: Text('Hello world'),
),
);
}
}
それじゃ、ソースコードを一つづつ詳しくみてみましょう。
import 'package:flutter/material.dart';
まず、私たちはFlutterが提供するmaterial
デザインを使ってプログラムを作成する予定です。
void main() {
runApp(MyApp());
}
Dartを勉強した方は、main
関数に慣れてると思います。main
関数はDartのプログラムを実行するための関数で、Flutterではこの関数でrunApp
関数をコールする必要があります。
Dartに関してよく分かってない方は、下記のリンクでDartに関して確認してみてください。
runApp
関数は一つのウィジェットをパラメータでうけっております。ここでセットされるウィジェットが私たちが作るFlutterアプリを構成する開始点になり、このウィジェットがウィジェットツーリの一番上に位置することになります。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeWidget(),
);
}
}
MyApp
は私たちが作ったカスタムウィジェットです。ウィジェットの名前は何でもいいですが、ここではMyApp
と指定します。このウィジェットはStatelessWidget
を継承しました。つまり、このウィジェットは動的な値を持ってないことになります。
全てのウィジェットは基本的build
関数を持ってます。このビルド関数はまた他のウィジェットをリターンする構造を持ってます。このようにウィジェット中でウィジェットを含めることで親子関係が形成され、ウィジェットツーリが生成されます。
今回の例題ではflutter/material.dart
が提供するMaterialApp
ウィジェットを使ってアプリを構成しました。MaterialApp
はhome
と言うパラメータを持ってます。
このhome
はアプリが実行されて初めて画面に表示されることを意味し、このパラメータでセットされたウィジェットが最初表示されます。
それじゃ、アプリの最初画面で表示されるHomeWidget
をみてみましょう。HomeWidget
はMyAppと同じようにStatelessWidget
を継承して作ったカスタムウィジェットで、どんな名前を使ってもいいですが、ここではHomeWidgetと指定しました。
class HomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HOME'),
),
body: Center(
child: Text('Hello world'),
),
);
}
}
HomeWidgetはflutter/material.dart
が提供するScaffold
と言うウィジェットをリターンしてます。Scaffoldウィジェットはmaterial
アプリで基本的使えるウィジェットで、このウィジェットを使うとappBar
とbody
など、画面を簡単に構成することができます。
Scaffold(
appBar: AppBar(
title: Text('HOME'),
),
...,
);
今回の例題にはこのScaffoldを使ってアプリのステータスバーを表示しました。appBarパラメータへAppBar
ウィジェットをパラメータで渡して、AppBarウィジェットにはtitleパラメータにText
ウェジェットを使ってHOME
と言う文字を表示しました。
Scaffold(
...,
body: Center(
child: Text('Hello world'),
),
);
アプリのbody
にはCenter
と言うウィジェットを使ってこウィジェットを画面の真ん中に表示するようにして、Text
ウィジェットを使ってHello world
と言う文字を表示しました。
Stateful widgetコーディング
Stateful widgetを理解するため、次のコマンドを実行してFlutternoプロジェクトを生成します。
flutter create stateful_widget
そして次のコマンドを使ってVSCodeを実行します。
cd stateful_widget
code .
このようにVSCodeが実行されたら、lib/main.dart
ファイルを開いて下記のように修正します。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeWidget(),
);
}
}
class HomeWidget extends StatefulWidget {
@override
_HomeWidgetState createState() => _HomeWidgetState();
}
class _HomeWidgetState extends State<HomeWidget> {
int counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget')),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => setState(() => {counter++}),
child: Icon(Icons.add)),
Container(
child: Text('$counter'),
margin: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 0.0),
),
ElevatedButton(
onPressed: () => setState(() => {counter--}),
child: Icon(Icons.remove)),
],
),
),
);
}
}
それじゃ、ソースコードを一つづつ詳しくみてみましょう。Stateless Widgetで説明した内容は省略します。
Statefulウィジェットを作る方法について説明します。Statefulウィジェットを生成するためにはまずStatefulWidget
を継承してウィジェットを作る必要があります。
class HomeWidget extends StatefulWidget {
@override
_HomeWidgetState createState() => _HomeWidgetState();
}
Statelessとは違ってbuild
を使わなくcreateState
を使います。createStateはState
と言うクラスを継承したカスタムStateをリターンする必要があります。
ここでリターンするカスタムStateは変更できる状態を持ってますし、変更できる状態によるウィジェットも持ってます。
class _HomeWidgetState extends State<HomeWidget> {
int counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: Center(
child: Row(
...,
children: [
...,
Container(
child: Text('$counter'),
margin: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 0.0),
),
...,
],
),
),
);
}
}
まず、変更されるStateを保存する変数を宣言します。ここではint couter = 0;
と言う変数を宣言しました。このように宣言した変数はTextウィジェットを使ってText('$counter')
をついて画面に表示するようにしました。
このState値を変更するためにはsetState
と言う関数を使う必要があります。この関数を使わないとStateを変更しても、画面に反映されないです。
ElevatedButton(
onPressed: () => setState(() => {counter++}),
child: Icon(Icons.add))
Stateについてのメカニズムは結構複雑なので、ここでは使う方法についてだけ説明します。メカニズムについて気になる方は公式サイトを参考してください。
- 公式サイト: StatefulWidget class
Closing Label
今まで例題をコーディングした時、次のように私たちが追加してないのに、自動で追加されたコメントが確認できます。
Flutterはたくさんのウィジェットを使ってアプリを作成します。このようにたくさんのウィジェットとたくさんのソースコードのせいで、一つのウィジェットがどこからどこまでかよく分からなくなります。この問題を解決するためFlutterはClosing Label
と言う機能をして、自動でウィジェットが終わるところにコメントを入れます。これで私たちはウィジェットがどこから初めてどこで終わるかもっと簡単に分かることができます。
このコメントは私たちは追加することも修正することもできません。
確認
これで簡単なコーディングをしてFlutterアプリの画面を構成する方法について調べてみました。コードを確認したら分かると思いますが、アプリを構成する全てのものがウィジェットだったことが分かります。
それじゃ、このように修正したアプリを実行してみます。アプリを実行するため、エミュレーターを実行して、Flutterプロジェクトを実行する方法については下記のリンクを確認してください。
このようにアプリを実行すると次のように私たちが作ったアプリが画面に表示されることが確認できます。
完了
これでFlutterを使って新しいプロジェクトを生成してみて、簡単な例題を使ってFlutterの主な要素であるウィジェットについて詳しくみてみました。Flutterはこのウィジェットを使って全てのアプリを構成するので、よく覚えておきましょう。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。