SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

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

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

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

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を設定すると、選択できないコントロールとして扱えます。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
チェックボックス

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
Flutterで始めるモバイルアプリ開発連載記事一覧

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/15268 2021/12/17 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング