入力フォーム2つ目。
前回は明確にSubmitしてもらうパターンだったけど、今回は随時更新するパターン。
例えば、ユーザーがプロフィール情報をアップデートするときに、入力したら自然と更新されてるみたいにするやつ。
で、やってみたものの、懸念点がいくつがあり。
とりあえずコード。
参考
https://stackoverflow.com/questions/48870082/managing-events-in-flutters-textformfield
import 'package:flutter/material.dart';
class FormListenerPage extends StatefulWidget {
@override
State createState() => _FormListenerPageState();
}
class _FormListenerPageState extends State {
String _lastSubmitValue = "初期値";
TextEditingController _textEditingController;
FocusNode _focusNode;
void _onChange() {
final _editingText = _textEditingController.text;
final _hasFocus = _focusNode.hasFocus;
// debugPrint("onChange: $_editingText, hasFocus: $_hasFocus"); // 確認用
// 変更があってフォーカスが外れた場合だけ実行(必要があればバリデートも)
if (_editingText != _lastSubmitValue && !_hasFocus) {
_lastSubmitValue = _editingText;
debugPrint("実行: $_editingText");
}
}
@override
void initState() {
super.initState();
_textEditingController = TextEditingController(text: _lastSubmitValue)..addListener(_onChange);
_focusNode = FocusNode()..addListener(_onChange);
}
@override
void dispose() {
_textEditingController.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('📮📮')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: ListView(
children: [
TextFormField(
decoration: InputDecoration(labelText: "ここをリッスン", border: OutlineInputBorder()),
controller: _textEditingController,
focusNode: _focusNode,
autofocus: true,
// onFieldSubmitted: onFieldSubmitted, // 無しでも_onChangeが動くからいらない
),
SizedBox(height: 16.0),
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.beach_access),
hintText: "上のTextFormFieldからフォーカス外し",
),
),
],
),
),
);
}
}
TextEditingControllerとFocusNode両方にイベント発生時の処理をセットして。
その処理の中で、それぞれの状態を確認して必要な処理を実行する感じです。
今回のケースではFocusNodeだけにセットで良いはずだけど、更新条件次第では必要だと思うので、備忘録的にTextEditingControllerにもセットしてます。
以下、懸念点など。
キーボードをバックボタンで消したときはフォーカスが外れないので、イベント自体は発行されるけど、通常の入力との使い分けができない。
方法はなにかしらあるかもだけど、そもそもキーボードで戻る = キャンセル的な意味合いだろうから、このタイミングでなにかを実行しようとするのが間違いなのかも。
画面自体のバック時にはフォーカスが外れるので実行されます。
Firestoreに保存するぐらいなら問題なく動いたけど、もっと長い処理を実行して結果をエラーダイアログを出すとかだと変なことになりそうな気もする。
そこも、構成によるとは思うけど。
といった感じで、ケースよにっては安心して使えないこともありそう。
onChange内の処理を調整するとか、一時保存的なケースでだけ使うとか。
しっかり考慮した方がよさそう。
それ以前にもっといい実装方法があるかもだけど。現時点ではこんな感じ。
