入力フォーム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内の処理を調整するとか、一時保存的なケースでだけ使うとか。
しっかり考慮した方がよさそう。
それ以前にもっといい実装方法があるかもだけど。現時点ではこんな感じ。