?!おえういあ
原因
TextField
を公式の リファレンス をもとに実装していたのですが、画面を StatefulWidget
↔ StatelessWidget
と切り替えたりしてゴチャゴチャしているうちに発生しました。
その時のコードの抜粋がこちらです。
class _MyHomePageState extends State<MyHomePage> {
String _message = '';
void _changeMessage(String newValue) {
setState(() {
_message = newValue;
});
}
@override
Widget build(BuildContext context) {
TextEditingController _controller = TextEditingController(text: _message);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_message,
style: Theme.of(context).textTheme.display1,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'メッセージ',
hintText: '入力すると上に表示されるよ',
),
onChanged: _changeMessage,
),
),
],
),
),
);
}
}
おわかりいただけただろうか?
@override
Widget build(BuildContext context) {
// 🐛🐛🐛
TextEditingController _controller = TextEditingController(text: _message);
// 省略
}
このアプリでは文字入力のたびに _changeMessage
メソッドで setState
しているんですが、 setState
したら build
メソッド呼ばれるんですよね……。
「 TextEditingController
更新されてる!!」
TextEditingController
はテキストの入力エリアを制御しているので、文字入力のたびにそれが初期化されて、フォーカス位置が初期化されていたみたいです
あいうえお!!
やったね!!
修正コード
class _MyHomePageState extends State<MyHomePage> {
String _message;
// 🎉🎉🎉
TextEditingController _controller;
void _changeMessage(String newValue) {
setState(() {
_message = newValue;
});
}
@override
void initState() {
super.initState();
_message = '';
// 🎉🎉🎉
_controller = TextEditingController(text: _message);
}
@override
void dispose() {
// 🎉🎉🎉
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_message,
style: Theme.of(context).textTheme.display1,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'メッセージ',
hintText: '入力すると上に表示されるよ',
),
onChanged: _changeMessage,
),
),
],
),
),
);
}
}
TextEditingController
を build
メソッドの外で作成するように変更しました。
まとめ
こんな事象に普通の人はならんだろw
StatefulWidget
のライフサイクルは理解しているつもりでしたが、ゴチャゴチャやってるうちに実装位置を間違えていたようです。
あまりお目にかかることはないと思いますが、発生しても焦らず、 State
の流れに注意してコードを見るようにしていきましょうね!
初心者向けで、ニッチな内容ですが、どなたかの役に立てれば幸いです