CodeZine(コードジン)

特集ページ一覧

Flutterのマテリアルデザインをフル活用! テキスト入力の設定・取得~ラジオボタン・チェックスボックスの入力コンポーネントを紹介

Flutterで始めるモバイルアプリ開発 第16回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2021/12/17 11:00

 前回は、テキスト入力フィールドの表示方法を中心に説明しましたが、今回はその続きで、入力値の取得方法と外部からの入力値の設定方法を紹介します。また、ラジオボタンとチェックスボックスの入力コンポーネントを紹介します。

目次

TextFormFieldの入力値の設定と取得

 前回までは主にテキストフィールドの表示方法についての説明でした。実際の利用ではサーバから取得したデータを入力フォームに設定したり、また、入力されたデータをサーバ上に保存したりします。その際は、必ず入力チェックなども必要です。今回は、このような場合に必要なTextFormFieldのデータの取り扱い方法を説明します。

初期値の設定

 まず最初に紹介するのが、コンポーネントを作成するときに初期値を設定する方法がリスト1です。一般的に初期値がプログラムで決められている場合に利用できる方法です。外部からデータを取得する場合であっても、画面作成時にはすでにデータが用意されている場合であれば利用可能です。

[リスト1]TextFormFieldを使ったサンプルコード(lib/textfield/TextFieldValueWidget.dartの抜粋)
TextFormField(
  initialValue: "INIT VALUE",
),

入力された値の取得方法

 続いて、入力された値を取得する方法を2つ紹介します。最初の方法が入力された値が変わったときに値を取得する方法です。値が変わったときのイベントを利用する方法で、その実装例がリスト2です。

[リスト2]TextFormFieldのonChangedを使った値の取得コード例(lib/textfield/TextFieldValueWidget.dartの抜粋)
// (省略)
// (1) 格納する文字列変数
String _loginId = "";

@override
Widget build(BuildContext context) {
  return Center(
    child: Padding(
      padding: EdgeInsets.all(10.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextFormField(
            // (2) 値が変わったときの処理
            onChanged: (value) {
              setState(() {
                _loginId = value;
              });
            },
          ),
          // (省略)
          Text(_loginId),
        ]
      )
    )
  )
}
// (省略)

 (1)は入力された文字列を格納する変数を用意しています。続いて、値が変更されたタイミングでonChangedで指定された関数が実行されるので、(2)のように値を設定する処理を記述します。このonChangedは値が変わる度に実行されます。JavaScriptなどで開発経験があれば、直感的に理解できる方法だと思います。

 続いて、入力が変化される度に入力値を知る必要がない場合があります。例えば、会員の登録画面などを想像してもらえばわかりやすいはずです。一般的に登録ボタンなどがあり、そのボタンを押したタイミングに設定されている値を取得したいというようなケースです。

 そのような場合に利用できるのがTextEditingControllerを利用する方法です。その実装例がリスト3です。

[リスト3]TextEditingController使ったサンプルコード(lib/textfield/TextFieldValueWidget.dartの抜粋)
// (1) コントローラ
final TextEditingController _textController = TextEditingController();
String _loginId = "";

@override
void dispose() {
  // (2) 必ず必要な処理
  _textController.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Center(
    child: Padding(
      padding: EdgeInsets.all(10.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          //
          TextFormField(
            // (3) 対象のコンポーネントに設定する
            controller: _textController,
          ),
          ElevatedButton(
            onPressed: () {
              setState(() {
                // (4) 値を取得する
                _loginId = _textController.text;
              });
            },
            child: Text("Submit")),
          // 省略
          ElevatedButton(
            onPressed: () {
              // (5) 値を設定する
              _textController.text = "ABCD1234";
            },
            child: Text("Set Value")),
          ],
       )));
}

@override
void initState() {
  super.initState();
  // (6) 値が変わったときの処理を登録
  _textController.addListener(() {
    print("changed value [${_textController.text}]");
  });
}

 まず、(1)のようにTextEditingControllerを作成します。忘れていけないのが、(2)のように画面が削除されるタイミングでTextEditingControllerの削除処理を実行する必要があります。TextFormFieldに(3)のように設定すると値をコントロールすることができます。値を取得する場合には、(4)のようにtextプロパティを読めばよく、値を設定する場合には(5)のようにします。

 コントローラを使っている場合にonChangedと同様に値が変わったときに処理を実行したい場合には(6)のように指定することができます。このようにTextEditingControllerを利用すればより高度のコントロールすることが可能です。こちらは、どちらかと言えばネイティブアプリの文化に近い形式のコードスタイルになります。

 外部から値を設定する必要がある場合には、こちらの方式を利用することになります。また、取得だけであればどちらでも可能なので、好きなほうを選んでよいでしょう。

入力チェックとエラーメッセージの設定

 前回、TextFormFieldのerrorTextに値を設定することでエラーチェックとエラーメッセージを表示することができるということを紹介しました。しかし、一般的にはアプリ内で入力チェックを行い、そのチェック結果に応じたエラーメッセージを設定するという利用をよくします。そのような方法がリスト4です。

[リスト4]Formと連携した値チェック方法のコード例(lib/textfield/TextFieldValidationWidget.dartの抜粋)
// (1) Form用のキーを作成する
final _formState = GlobalKey<FormState>();

@override
Widget build(BuildContext context) {
  // (2) Formを使う
  return Form(
    // (3) 設定する
    key: _formState,
    child: Padding(
      padding: EdgeInsets.all(10.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextFormField(
              // (4) 値をチェックする
              validator: (value){
                if(value == null || value.isEmpty){
                  return "入力してください";
                }
                return null;
              }
            ),
            ElevatedButton(
              onPressed: () {
                // (5) 値をチェックする
                _formState.currentState!.validate();
              },
              child: Text("値をチェックする")),
            ],
  )));
}

 GlobalKeyを使うとコンポーネントの実体(State)を参照することができます。FlutterではUIを宣言型で定義していくために、宣言したコンポーネントのインスタンスに相当するような実体にアクセスすることが難しくなります。

 特に、コンポーネントのツリー構造にとらわれず参照したいことが多くなります。そのため、(1)のように作成したキーを(2)のようにFormコンポーネントの(3)のように設定します。

 Formコンポーネントは、FormFieldを扱うためのコンテナコンポーネントです。これまで紹介しませんでしたが、テキスト入力コンポーネントにはTextFieldというものがあります。

 TextFieldとTextFormFieldの違いはほとんどなく、Formコンポーネントが管理できるようにしたTextFieldがTextFormFieldです。従って、Formと共に利用する場合には、TextFormFieldを必ず使用する必要があります。そして、値をチェックするルールを(4)のように記述することができ、エラーメッセージを返せば自動的に設定されます。値のチェックをするタイミングは(5)のようにボタンを押したタイミングなどのように任意に指定できます。

ラジオボタン(Radio)

 続いて、ラジオ(Radio)について紹介します。ラジオボタンは複数の選択肢の中から1つだけ選択する場合に利用する形式で、図1のような表示になります。また、その実行コード例がリスト5です。

図1:Radioを使ったコードの実行例
図1:Radioを使ったコードの実行例
[リスト5]Radioを使ったコード例(lib/radio/RadioWidget.dartの抜粋)
class _RadioWidget extends State<RadioWidget> {

  // (1) 選択済みの値を保存する変数
  int _selectedValue = 1;

  @override
  Widget build(BuildContext context) {
    return Container(
        color: Colors.white,
        alignment: Alignment.center,
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ListTile(
                title : Text('Value 1'),
                leading: createRadio(1),
              ),
              // : (省略)
            ])
    );
  }
  Radio createRadio(int dataValue){
    return Radio(
      // (2) 選択グループ
      groupValue: _selectedValue,
      // (3) 値が変わったとき
      onChanged: (value) {
        setState(() {
          _selectedValue = value;
        });
      },
      // (4) 選択されたときの値
      value: dataValue,
    );
  }

  // : (省略)

  // (5) 利用できないボタン
  Radio createDisableRadio(){
    return Radio(
      onChanged: null,
      // : (省略)
    );
  }
}

 (1)は選択済みの値を保存する変数です。この変数は(2)のようにgroupValueプロパティに設定することで、複数のラジオボタンをグループ化して扱うことができます。チェックされたときには(3)のようにonChangedメソッドが実行されるので、そこで(1)での変数に値を設定します。そして、(4)が選択されたときの値を指定します。TextFormFieldと同様にonChangedにnullを設定すると、選択できないコントロールとして扱えます。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Flutterで始めるモバイルアプリ開発

もっと読む

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5