2020/10/18 Flutter : Handle changes to a text fieldの訳

ページの一番下にこのページで説明していることの全てを含む完全なサンプルコードがありますので、そちらを最初に見た方が良いかもしれません。

テキストフィールドに入力されたテキストが変更されるたびに特定のコールバックを呼び出したい、という場面はよくあります。たとえば、ユーザーの入力に応じて結果を更新するオートコンプリート機能を備えた検索画面を作成したい場合があります。

このような機能を実装する場合Flutterでは以下の二つの選択肢があります。

  1. TextFieldウィジェット、あるいはTextFormFieldウィジェットのonChanged()コールバックを設定する。
  2. TextEditingControllerウィジェットを使用する。

1.TextFieldウィジェット、あるいはTextFormFieldウィジェットのonChanged()コールバックを設定する。

最もシンプルな選択肢はTextFieldウィジェット・TextFormFieldウィジェットのonChangedプロパティにコールバックを設定する方法です。テキストが変更する度にコールバックが呼び出されます。

以下のサンプルはテキストが変更する度にコンソールに現在の入力文字列が表示される例です。

TextField(
  onChanged: (text) {
    print("First text field: $text");
  },
);

2.TextEditingControllerを使用する。

よりパワフルな選択肢として、TextFieldウィジェット・TextFormFieldウィジェットのcontrollerプロパティにTextEditingControllerクラスのインスタンスを設定する方法があります。

テキストが変更した時にその旨の通知を受けるには、次のステップに沿ってaddlistener()メソッドを使ってコントローラーをリッスンします。

  1. TextEditingControllerを生成する。
  2. TextEditingControllerをテキストフィールドに接続する。
  3. 現在の文字列値を表示する関数を宣言する。
  4. 変更を察知するためにコントローラーをリッスンする。

Step1.TextEditingControllerを生成する。

// ↓カスタムのフォームウィジェット「MyCustomForm」を定義する。

class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

// 対応するStateクラスを定義する。
// このクラスがフォームのデータを保持する。
class _MyCustomFormState extends State<MyCustomForm> {

  // ↓text controllerを生成する。
  //後にこのコントローラーを使用してテキストフィールドの現在の値を取得する。
  final myController = TextEditingController();

  @override
  void dispose() {
    // このウィジェットがウィジェットツリーから除去された時にコントローラーをクリーンアップする。
    myController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //次のステップでこの部分を実装する。
  }
}

Note:TextEditingControllerが必要なくなった時にdisposeメソッドを実行するようにしてください。それにより、不要なオフジェクトがリソースを占有し続ける状況を避けることができます。


Step2.TextEditingControllerをテキストフィールドに接続する。

Step1で生成したmyControllerを、TextFieldウィジェット、あるいはTextFormFieldウィジェットのcontrollerプロパティに設定する。このように設定すれば、そのテキストフィールドの値の変化をリッスンすることができるようになります。

TextField(
  controller: myController,
);

3.現在の文字列値を表示する関数を宣言する。

テキストが変更される度に実行される関数を宣言する必要があります。_MyCustomFormStateクラス内に、テキストフィールドの現在値を表示するメソッド(_printLatestValueメソッド)を宣言します。

_printLatestValue() {
  print("Second text field: ${myController.text}");
}

4.変更を察知するためにコントローラーをリッスンする。

最後に、TextEditingControllerインスタンスをリッスンして、テキストが変更された時に_printLatestValue()メソッドが呼び出されるようにします。

そのためにaddListener()メソッドを実行します。

_MyCustomFormStateクラスがイニシャライズされた時に「入力値の変更のリッスン」が始まります。そして_MyCustomFormStateがdisposeされた時にリッスンが終わります。


まとめのサンプル

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Retrieve Text Input',
      home: MyCustomForm(),
    );
  }
}

// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

// Define a corresponding State class.
// This class holds data related to the Form.
class _MyCustomFormState extends State<MyCustomForm> {
  // Create a text controller and use it to retrieve the current value
  // of the TextField.
  final myController = TextEditingController();

  @override
  void initState() {
    super.initState();

    myController.addListener(_printLatestValue);
  }

  @override
  void dispose() {
    // Clean up the controller when the widget is removed from the widget tree.
    // This also removes the _printLatestValue listener.
    myController.dispose();
    super.dispose();
  }

  _printLatestValue() {
    print("Second text field: ${myController.text}");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Retrieve Text Input'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            TextField(
              onChanged: (text) {
                print("First text field: $text");
              },
            ),
            TextField(
              controller: myController,
            ),
          ],
        ),
      ),
    );
  }
}

二つのテキストフィールドが上下に配置されています。

上のテキストフィールドがFirst text field

下のテキストフィールドがSecond text field

First text fieldは「TextFieldウィジェットのonChangedプロパティにコールバックを設定する方法」を使って文字列値の変化をリッスンしています。

Second text fieldは「TextEditingControllerを使用する方法」を使って文字列値の変化をリッスンしています。

 

 

参考

https://flutter.dev/docs/cookbook/forms/text-field-change

コメントを残す

メールアドレスが公開されることはありません。