プログラミング初心者が始めるFlutter学習③-1
こんにちは。PHR事業開発部の大岡です。
私の回は、Flutterのソースコードを解説していくシリーズになっています。
これまでの記事はこちらです。
今回は、前回までに作った入力フォームの他に、ピッカーやラジオボタンを使って、いくつかのデータを入力できるようにします。
入力したデータをアプリ内で保存するところまで行きたかったんですが、入力画面だけで今回は終わりそうです。。
ソースコードはこちらです。
https://github.com/psp-engineer/data_input
■データ入力画面を作る
氏名(入力フォーム)、性別(ラジオボタン)、出身地(ドラムロールピッカー)の入力欄と「次へ」ボタンを作成する
画面はこのようになります。
分量が増えてきたので、見やすくするために、入力するパーツごとにメソッドにしてみました。
// 画面描画を書いているところ
@override
Widget build(BuildContext context) {
return Scaffold(
// 一番上のタイトルが表示されているところ
appBar: AppBar(
title: Text(widget.title),
),
// 画面のメインの部分
body: Align(
// 画面の真ん中に位置させる
alignment: Alignment.center,
// 画面に収まりきらない時にスクロールできるようにする
child: SingleChildScrollView(
// Widgetを縦に並べる
child: Column(
children: <Widget>[
// 氏名
nameInputForm(),
// 性別
genderInputForm(),
// 出身地
regionInputForm(),
// 次へボタン
nextButton(),
],
),
),
),
);
}
このコードの下でnameInputForm()、genderInputForm()などの具体的な中身を書いていきます。
また、入力されたデータはそれぞれ_name(氏名)、_gender(性別)、_region(出身地)に格納されるようにします。
nameInputForm()とnextButton()は前回までに作った入力フォームをそのまま使っているので省略します。
genderInputForm()
ラジオボタンで性別を選択する部分です。
Widget genderInputForm() {
return Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Text(
'性別',
style: TextStyle(fontSize: 18.0),
)),
// 子Widgetの周りに余白を作る
Padding(
// 余白の幅やどこに付けるかを指定
padding: const EdgeInsets.only(bottom: 25.0),
// 子Widgetを横に並べる
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// ラジオボタン
Radio(
// このラジをボタンを押した時にonChangedでvalueに入ってくる値
value: Gender.male,
// ここで設定した値(ここでは_gender)がvalueに設定した値(ここではGender.maile)と一致する時、このラジオボタンがアクティブになる
groupValue: _gender,
// ボタンのON、OFFが変わるたびにこの関数を実行
onChanged: (Gender? value) {
if (value != null) {
_setGender(value);
}
},
),
const Text('男'),
Radio(
value: Gender.female,
groupValue: _gender,
onChanged: (Gender? value) {
if (value != null) {
_setGender(value);
}
},
),
const Text('女'),
Radio(
value: Gender.other,
groupValue: _gender,
onChanged: (Gender? value) {
if (value != null) {
_setGender(value);
}
},
),
const Text('その他'),
],
),
),
],
);
}
ここで、Radio()ウィジェットのvalueに指定しているGender.maleは、enumというクラスです。
列挙型とも呼ばれ、関連する定数を一括りにするためのクラスです。今回は性別の選択肢をまとめてGenderというenumを作りました。
これだけだと必要性があまり感じられないかもしれませんが、定数として定義することで、スペルミスしたときに教えてくれたり、それぞれの定数に引数として属性のようなものを設定できたりします。
enum Gender {
male,
female,
other,
none,
}
今回の場合は、例えばラジオボタンの「男」を選択すると下記の_setGender(value);が実行されてGender.maleが_genderに入ります。
void _setGender(Gender selectedGender) {
// 選択された性別のenumを_genderに代入
setState(() {
_gender = selectedGender;
});
}
regionInputForm()
ドラムロールピッカーなどと呼ばれる、選択肢を上下にくるくる動かして選択するピッカーで、出身地を選択する部分です。
Widget regionInputForm() {
return Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Text(
'出身地',
style: TextStyle(fontSize: 18.0),
)),
// 子Widgetの周りに余白を作る
Padding(
// 余白の幅やどこに付けるかを指定
padding: const EdgeInsets.only(bottom: 25.0),
child: TextFormField(
// ピッカーで選択した地域をTextFormFieldに表示させるためのcontrollerを設定
controller: _controller,
decoration: const InputDecoration(
// 何も入力されていない時に表示するヒントテキスト
hintText: '関東',
),
onTap: () {
// タップした時にキーボードが出ないようにする
FocusScope.of(context).requestFocus(FocusNode());
// ピッカー(_showDialogはさらに下で定義)
_showDialog(
CupertinoPicker(
itemExtent: 32.0,
// ピッカーの値が変化するたびに_setRegionを実行
onSelectedItemChanged: (int selectedItem) {
_setRegion(selectedItem);
},
// ピッカーの項目を設定
children: List<Widget>.generate(_regionNames.length, (int index) {
return Center(
child: Text(
_regionNames[index],
),
);
}),
),
);
},
),
),
],
);
}
// ピッカーの選択肢として表示する項目のList
final List<String> _regionNames = <String>[
'北海道',
'東北',
'関東',
'中部',
'近畿',
'中国・四国',
'九州',
];
TextFormField()をタップしたらピッカーが出てくるようにしたいので、TextFormField()のonTap: に_showDialog()としてピッカーを設定しています。
void _showDialog(Widget child) {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) => Container(
height: 216,
// 余白の幅やどこに付けるかを指定
padding: const EdgeInsets.only(top: 6.0),
// Widgetの内側に余白を作る
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
// ピッカーの背景色を指定
color: Colors.white70,
// 子Widgetがスマホ画面からはみ出さないようにする
child: SafeArea(
// 上部だけSafeAreaを無効にする
top: false,
child: child,
),
));
}
これで入力画面ができました。文字や選択項目を入力できるようになったはずです。
入力画面のウィジェットなどについて説明するだけで結構な長さになってしまいました、、続きはまた次回です。
どんどん進みが遅くなっていますが、なんとか続けていきたいと思います。
誰かの理解の助けになれば嬉しいです。
次回は、入力したデータを次のページで表示させるのと、入力データの保存までいけたらいいなと思っています。