詳解 TextField

Masahiro Aoki
19 min readAug 8, 2022

--

よりよいUI/UXを求めて。

Flutterエンジニアなら知らない人はいないTextField ウィジェット。しかしそのプロパティ数は膨大であり、全てを把握・活用するのは至難の業ではないでしょうか。今回はそのTextFieldを可能な限り詳しく解説しました。また、サンプルコード、画像、Gif等をたくさん用意しましたので、楽しく・わかりやすく学べるようになっていると思います。初学者から経験者まで、TextFieldに興味がある方の学習の一助になれば幸いです。

今回のサンプルコードは全てGitHubに上がっています。実際に触りたい方はFlutter for Webでdeployしましたので、こちらからアクセスしてください。

入門 TextField

TextFieldはユーザーが入力した情報を受け取るために利用します。基本的な使い方は以下の通りです。

TextField();

このコードで次のようなシンプルなTextFieldを作成することができます。

https://flutter-dictionary-release.web.app/textFieldTop/textField

TextFieldから値を取得

  1. TextFieldに入力された値を取得するにはonChangedコールバックを使用し、変数に値を代入します。
String value = '';
TextField(
onChanged: (text) {
value = text;
}
);
https://flutter-dictionary-release.web.app/textFieldTop/onChanged

2. TextEditingControllerの使用も可能です。controllerプロパティにTextEditingControllerのオブジェクトを指定することにより、値の変更をリッスンし制御することができます。

TextEditingController controller = TextEditingController();
TextField(controller: controller);

以下のようにリッスンすることができます。

controller.addListener(() {
// do something!
});

以下のように値を取得したり、代入することができます。

print(controller.text);
controller.text = 'Lorem ipsum';

メモリリークを防ぐため、使用後には必ずオブジェクトをdisposeしてくださいね。

@override
void dispose() {
controller.dispose();
super.dispose();
}

他のコールバック

TextFieldウィジェットにはonChanged以外に以下のコールバックが存在します。

  1. onSubmitted

入力が完了した時に呼び出されるコールバックの1つです。

例えば、iOSでは、virtual keyboardのdoneを、webではenterを押した時に発火します。また、入力値を引数として受け取ることができます。

発火後virtual keyboardは自動的に閉じられます。

TextField(
onSubmitted:(value){
// do something
});

以下の例では、入力した値をAlertDialogで表示しています。

3. onEditingComplete

キーボード上のdoneやnextをタップした時に発火します。
こちらはonSubmittedと異なり、引数を持ちません。
また、コールバック内でunfocus()を呼び出す場合、キーボード上の送信ボタンの種類(TextInputAction)により、virtual keyboardの開閉挙動が異なります。

(unfocus()を呼び出さない場合は、unfocusされることはありません)

onEditingComplete: () {
focusNode.unfocus();
}
  1. go, send, search
    textEditingControllerに値が入力され、TextFieldのフォーカスが失われ、キーボードが閉じます。

2. continue, next, previous
textEditingControllerに値が入力されますが、TextFieldのフォーカスは失われず、キーボードは閉じられません。

onSubmittedとonEditingCompleteの使い分け

引数があるか否かが一番の違いになります。

3. onTap

TextFieldがタップされた時に発火します。ただし発火上限は1秒間に1回までです。

TextField(
onTap:(){
print('tapped');
}
);

フォーカス

TextFieldにフォーカスを当てると、TextFieldが有効になり、キーボードからの入力を受けとることが可能になります。

1. オートフォーカス

Widgetが描画された時点で、自動的にフォーカスを当てることが可能です。

TextField(autofocus:true);
https://flutter-dictionary-release.web.app/textFieldTop/autofocus

2. フォーカス対象の変更

フォーカスを当てるTextFieldを変更したい場合は、requestFocus()を使用して、フォーカスを変更します。

サンプルでは、TextFieldの2つ作り、1つめの入力が終了した時点で次のTextFieldへフォーカスを当てています。

FocusNodeオブジェクトは必ずdisposeし、メモリリークを防ぎましょう。

late FocusNode focusOne;
late FocusNode focusTwo;
@override
void initState() {
super.initState();
focusOne = FocusNode();
focusTwo = FocusNode();
}
@override
void dispose() {
focusOne.dispose();
focusTwo.dispose();
super.dispose();
}
TextField(
focusNode:focusOne,
onSubmitted:(_) {
FocusScope.of(context).requestFocus(focusTwo);
}
),
TextField(focusNode:focusTwo),

Virtual Keyboardのカスタマイズ

iOSおよびAndroidのVirtual Keyboardをユースケースに合わせてカスタマイズすることがで可能です。

もちろん、virtual keyboardの存在しないiOS・Android以外のプラットフォームでは、指定する意味はありません。

1. Keyboard Type

keyboardTypeを指定しない場合、次のようなキーボードが表示されます。

しかし、例えば数字を入力させたい場合、最初から数字が表示されていればUXが高まります。

次のように指定してあげると、数字キーボードが初回から表示されます。

TextField(keyboardType:TextInputType.number);

またお気づきの通り、数字キーボードから文字入力キーボードへの変更が不可能になっています。入力値を数字のみに制限したい場合にも活用できます。

keyboardTypeは数字以外に以下のバリエーションが存在します。

  1. TextInputType.none (キーボードは非表示)
  2. TextInputType.datetime

3. TextInputType.emailaddress

4. TextInputType.multiline
複数行の入力が前提になっているので、doneではなくreturnで改行するようになっています。

5. TextInputType.phone

6. TextInputType.name, TextInputType.streetAddress, TextInputType.text, TextInputType.visiblePassword

7. TextInputType.url

2. TextInputAction

textInputActionを変更することにより、virtual keyboardの実行ボタンを変更することができます。

TextField(textInputAction: TextInputAction.continueAction):

デフォルトでは「done」ですが、「continue」に変更されています。

  1. TextInputAction.done

2. TextInputAction.emergencyCall
Androidの使用不可

3. TextInputAction.go

4. TextInputAction.join
Androidの使用不可

5. TextInputAction.newline

6. TextInputAction.next

7. TextInputAction.none
iOSは使用不可

8. TextInputAction.previous
iOSは使用不可

9. TextInputAction.route
Androidは使用不可

10. TextInputAction.search

11. TextInputAction.send

12. TextInputAction.unspecified
Androidの場合はdone or returnが表示されます。

3. Autocorrect

タイプミスを自動修正するか否かを決めることができます。

デフォルトではtrueになっていますが、falseにすることもできます。

TextField(
autocorrect: false,
),

4. Text Capitalization (大文字化)

英語で文章を作成する時に、大文字化をしてくれます。
(iOSおよびAndroidのみ利用可能)

TextField(
textCapitalization: TextCapitalization.sentences,
),

The types are:

  1. TextCapitalization.sentences

文頭が大文字になります。

2. TextCapitalization.characters

全ての大文字になります

3. TextCapitalization.words

単語の1文字目が大文字になります。

文字列のスタイル、整列、カーソル変更

Flutterでは、TextField 内の文字列のスタイルや整列(Alignemnt)を変更することができます。それだけではなく、カーソルもカスタマイズすることが可能です。

Alignementの変更

textAlignプロパティを利用し、文字列の整列をします。

以下の場合、文字列は左揃えになります。

TextField(
textAlign: TextAlign.start,
),

startだけでなく、center, right, end, right, left, そして justifyがあります。

文字列のスタイルを変更

styleプロパティにはTextStyle()を指定することができます。フォントや文字サイズ、色等を変更可能です。

サンプルでは、GoogleFontsパッケージを使用し、inspirationフォントを使用しました。

TextField(
style: GoogleFonts.inspiration(
color: Colors.deepPurpleAccent[700],
fontSize: 30,
fontWeight: FontWeight.bold,
)

カーソルをカスタマイズ

カーソルはTextFieldから直接カスタマイズすることが可能です。

TextField(
cursorColor: Colors.deepPurpleAccent[700],
cursorHeight: 30,
cursorWidth: 10,
cursorRadius: const Radius.circular(16.0),
),

カーソルの非表示

TextField(
showCursor: false,
)

マウスカーソルの指定

webやdesktop環境の場合、マウスカーソルの指定も可能です。

TextField(
mouseCursor: SystemMouseCursors.click,
)

文字数制限

TextField(
maxLength: ,
),

TextFieldに入力できる文字数を制限することが可能です。

複数行入力

行数指定

maxLinesプロパティを使用すれば、行数を設定可能です。

TextField(
maxLines: 2,
)

行数未指定

ユーザーが入力する行数がわからない場合は、maxLinesにnullを指定することにより、行数の制限をなくすことが可能です。

TextField(
maxLines: null,
)

文字列の非表示

パスワード等を入力する場合、文字列を非表示にすることが可能です。

TextField(
obscureText: true,
),

非表示の文字を変更

デフォルトでは「・」が利用されており、1文字であれば変更可能です。
(ただし、絵文字等の長さは必ずしも1にはなりませんので、注意が必要です。)

TextField(
obscureText: true,
obscuringCharacter: '?',
)

TextFieldの装飾(Decoration)

TextFieldのdecorationプロパティにInputDecoration クラスを指定し、装飾を変更します。

label

TextField(
decoration: InputDecoration(
label: const Text('label'),
),
);

hintText

TextField(
decoration: InputDecoration(
hintText: 'hint text'
),
);

icon

TextField(
decoration: InputDecoration(
icon: Icon(Icons.check)
),
),

prefixIcon

TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.check)
),
),

suffixIcon

TextField(
decoration: InputDecoration(
suffixIcon: Icon(Icons.check)
),
),

prefix

prefixにIcon クラスではなく、Widgetを指定したい場合は、prefixプロパティを使用します。

TextField(
decoration: InputDecoration(
suffixIcon: CircularProgressIndicator.adaptive(),
),
),

helperText

TextField(
decoration: InputDecoration(
helperText: "helper text"
),
),

border

TextField(
decoration: InputDecoration(
border: OutlineInputBorder()
)
),

下線の無効化

以下2つの方法で下線を削除可能です。

TextField(
decoration: InputDecoration.collapsed(hintText: "")
),
TextField(
decoration: null
),

下線の色の変更

TextField(
decoration: const InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
),

最後に

長文にお付き合いいただきありがとうございます。本記事はまだまだ完璧から程遠いため、間違いやアドバイス等ありましたら、お手数をおかけしますが、コメントやまで連絡を頂けると助かります。

また、詳しく知りたいWidget等ありましたら、こちらもご教授いただければ幸いです。次の記事の参考にさせていただきます!

参考資料

--

--