LoginSignup
5
2

More than 3 years have passed since last update.

Flutter の TextField で「?!おえういあ」と入力されてしまう貴方へ

Posted at

?!おえういあ

flutter_text_field_bug.gif

原因

TextField を公式の リファレンス をもとに実装していたのですが、画面を StatefulWidgetStatelessWidget と切り替えたりしてゴチャゴチャしているうちに発生しました。

その時のコードの抜粋がこちらです。

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 はテキストの入力エリアを制御しているので、文字入力のたびにそれが初期化されて、フォーカス位置が初期化されていたみたいです :scream:

あいうえお!!

flutter_text_field_success.gif

やったね!!

修正コード

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,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

TextEditingControllerbuild メソッドの外で作成するように変更しました。

まとめ

こんな事象に普通の人はならんだろw
StatefulWidget のライフサイクルは理解しているつもりでしたが、ゴチャゴチャやってるうちに実装位置を間違えていたようです。

あまりお目にかかることはないと思いますが、発生しても焦らず、 State の流れに注意してコードを見るようにしていきましょうね!

初心者向けで、ニッチな内容ですが、どなたかの役に立てれば幸いです :yum:

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2