作って学ぶ、Flutterアプリ開発 〜入力データの制御〜
はじめに
こんにちは。
この記事はこちらの記事の続きです。
アプリをまだ作っていない人はこちらから進めていただくとスムーズかと思います!
それでは、前回予告した通りに、TODOリストに空のデータが含まれてしまっているので、それをなんとかしたいと思います。
実装
前回までのnoteを読んでアプリを作ってくれている場合には、右下の「+」ボタンをタップするとこんなダイアログが出てくるかと思います。
このダイアログ、「追加」ボタンが常に押せる状態になっています。
なので、何も入力せずに「追加」ボタンを押してしますと空のデータが登録されてしまいます。
どうすればいいでしょうか?
色々方法はあると思いますが、ここでは何も入力がない場合には「追加」ボタンを押せなくしようと思います。
このダイアログの実装はこうなっているかと思います。
AlertDialog(
title: const Text('TODOを追加'),
content: TextField(
controller: _textController,
autofocus: true,
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('キャンセル'),
),
TextButton(
onPressed: () {
// 追加ボタンが押された時にここの実装が反映されます
setState(() {
_todoList.add(_textController.text);
});
_textController.clear();
Navigator.pop(context);
},
child: const Text('追加'),
),
],
);
})
ダイアログはAlertDialogというWidgetを使っていましたね。
AlertDialogはStatelessWidgetなので、動的に状態を変更できません。
なので、AlertDialogをStatefulBuilderで囲んであげます。
StatefulBuilder(builder: (context, setState) {
return AlertDialog(
title: const Text('TODOを追加'),
content: TextField(
controller: _textController,
onChanged: (value) {
setState(() {
// ここの説明はこのあとします
if (value.isNotEmpty) {
isEdited = true;
} else {
isEdited = false;
}
});
},
autofocus: true,
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('キャンセル'),
),
TextButton(
onPressed: isEdited // ここの説明はこのあとします
? () {
// 追加ボタンが押された時にここの実装が反映されます
setState(() {
_todoList.add(_textController.text);
});
_textController.clear();
Navigator.pop(context);
}
: null,
child: const Text('追加'),
),
],
);
})
ここまでできましたか?
コードの途中にコメントしましたが、「追加」ボタンのところにisEditedというコードが増えていますね。
まずは、このclassの一番上、TextEditingControllerなどを書いているところと同じところにisEditedを追加してください。
var isEdited = false;
このisEditedはboolと呼ばれる変数で、true(真)またはfalse(偽)の値を持ちます。
初期値はfalseにしておきましょう。
TextButton(
onPressed: isEdited
? () {
// 追加ボタンが押された時にここの実装が反映されます
setState(() {
_todoList.add(_textController.text);
});
_textController.clear();
Navigator.pop(context);
}
: null,
child: const Text('追加'),
),
「追加」ボタンのonPressedにnullという値を渡してあげると、ボタンが押せなくなります。
このコードが何をしているかというと、isEditedがtrueの時には() {}という関数を渡してタップされたらその中に書かれているコードを実行してください。
isEditedがfalseだったらnullにしてください。
というコードになります。
onPressedがnullになっていると、こんな風に「追加」ボタンがグレーになってタップしても何も起きなくなります。
では、isEditedのtrue、falseはどこで変更しているかを見てみましょう。
TextField(
controller: _textController,
onChanged: (value) {
setState(() {
if (value.isNotEmpty) {
isEdited = true;
} else {
isEdited = false;
}
});
},
autofocus: true,
)
TODOの文字を入力しているTextFieldというWidgetにはonChanedという関数を受け入れる機能があります。
(value) {}という関数を渡しています。
このvalueには入力した文字が変更される度に入ってきます。
if (value.isNotEmpty) {} else {} というコードはもしvalueの値は空ではなかったら、isEdited = true;にする、そうでなければisEdited = false;にすると書いてあります。
つまり、入力があれば「追加」ボタンを押せる状態にする(活性化する)、入力がなければ押せなくする(非活性化)というプログラムを書いた事になります。
ここまでできましたでしょうか?
今回はもうひと押し、ダイアログの「キャンセル」ボタンが押された時に入力された文字をクリアしてみましょう。
今は文字の入力がある状態で「キャンセル」ボタンを押したとしても、次にもう一度「+」ボタンを押すと前の入力が残ったままになっていますね。
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('キャンセル'),
)
「キャンセル」ボタンのonPressedのコードはこうなっています。
Navigator.pop(context);というのはダイアログを閉じますというコードです。
これに加えて、入力された文字をクリアしましょう。
入力文字をクリアするコードは既に使っています。
ピンと来た方は答えを見る前に書いて動作確認してみてください。
ちょっとスペース開けますね。
答えです。
TextButton(
onPressed: () {
_textController.clear();
Navigator.pop(context);
},
child: const Text('キャンセル'),
)
AlertDialogの「キャンセル」ボタンのonPressedが押された時に実行されるコードです。
どうですか?
正解しましたか?
これでダイアログの「キャンセル」ボタンを押した場合には入力された文字が消えますので、最初から入力できます。
まとめ
ここまでどうでしたか?
上手く動いていれば幸いです。
もし途中でよくわからなくなってしまったなどありましたら、コメントいただければお答えできるかと思いますので、遠慮なくコメントください。
さて、ここまで作ってきましたがこのTODOアプリですがリストの内容や完了したかどうかという内容をどこにも保存できていません。
アプリを再起動するとリストもチェックも消えてしまいますよね。
なのでどこかに保存しなければなりません。
次回からはいくつかデータを保存しておく方法について書いていきたいと思います。
それではまた宜しくお願い致します。
この記事が気に入ったらサポートをしてみませんか?