[Flutter]Issueから考えるautofill+autocorrect問題
1行まとめ
FlutterのTextFieldやTextFormFieldにautofillHintsを指定する場合には、autocorrectをfalse
に設定しよう。
以下、詳細です。
autofillHints
とautocorrect
TextField
やTextFormField
には、autofillHints
プロパティとautocorrect
プロパティがあります。これらは適切に組み合わせるべきプロパティです。不適切な組み合わせは、特定の環境で問題を引き起こす可能性があります。
この記事では、FlutterにおけるautofillHints
とautocorrect
の適切な指定について考察します。
autofillHints
autofillHints
は入力フォームに自動入力するためのヒントを提供します。デフォルト値はnull
です。
ユーザーにメールアドレスを入力してもらう場合、autofillHints
にAutofillHints.emailを指定することで、自動入力の候補が表示されるようになります。意味合いとしてはkeyboardTypeと似ていますが、keyboardType
はキーボードの種類を指定するのに対して、autofillHints
は自動入力のヒントを指定するという違いがあります。
FormとAutofillGroupを組み合わせるケースが大半でしょう。たとえばAutofillHints.usernameとAutofillHints.passwordによるログイン機能が典型例です。そのほか、クレジットカード情報であったり、住所情報であったりを自動入力できます。
ユーザービリティを高めることができるため、筆者のお気に入りの機能です。[1]
autocorrect
autocorrect
は、テキスト入力中に自動修正するかどうかを指定します。デフォルト値はtrue
です。
調べてみると、この"correct"が何を意味するかは、Flutterが各プラットフォームのAPIをどの様に呼び出しているかに依存します。筆者が調べた範囲では、iOSでは自動修正とスペルチェックをセットで管理し、Androidでは自動修正のみを管理しているようです。Webはブラウザごとにサポート状況が異なっており、Safariの場合には言語によっては自動修正が行われるようです。
iOSのソフトウェアキーボードのパスワード欄がちらつく問題
iOS 17より、ソフトウェアキーボードのパスワード欄のちらつき問題が発生しています。
筆者の調査によると、この問題は「iOSのソフトウェアキーボードがパスワード欄を表示する際に、autocorrect
がtrue
の場合に発生」します。このため、autocorrect
をfalse
に設定することで問題を回避できます。
PRでは、パスワードマネージャーを呼び出す設定が有効な場合、autocorrectionType
とspellCheckingType
をNoに設定することで問題を回避しました。
この動作は、UIKitのUITextFieldを利用するケースでも同様のようです。FlutterはiOSのUITextFieldをラップしているため、このような問題が発生していると考えられます。PRに添付した再現するプロジェクトを添付したので、興味がある方は試してみてください。
なお、SwiftUIの場合はパスワードにSecureFieldを利用することでこの問題を回避できましたが、ユーザー名にTextFieldを利用する必要があるため回避できませんでした。詳しい方がいれば、どうするのがいいのかコメントいただけると助かります。
autocorrect
は設定するべきなのか?
autocorrect
のデフォルト値はtrue
です。このため、autocorrect
の設定を意識したことがない開発者も多いのではないかな、と思います。[2]
今一度「autocorrect
を設定することは、ユーザーにとって便利なのか」を考えてみるのはいかがでしょうか。
筆者の個人的な経験になりますが、ユーザー名にautocorrect
が設定されていたために、「正しいメールアドレスを入力したのに単語を修正された」ことがあります。具体的には(zennのアカウント名でもある)koji
を入力すると、koki
に修正されがちです。また、パスワードの入力欄にはautocorrect
を設定するべきでないことは明らかです。もしもパスワードがautocorrect
されてしまった場合、ユーザーが"正しくない"英単語を用いたパスワードを設定しにくくなってしまいます。
その他のケースを考えてみると、そもそもautofillHints
を設定するようなTextField
にautocorrect
を設定するメリットがあるのか、という疑問が湧いてきます。見渡す限り、メリットよりもデメリットの方が上回るように感じます。
「ここはautocorrect
されて欲しい」というTextField
に対して、限定的にautocorrect
を設定する方が、結果的にユーザーにとって良い体験になるのではないでしょうか。筆者はデフォルト値がtrue
であることに疑問を感じています。とはいえ、この値が変わることはまずないため、開発者がautocorrect
に注意を払うことが重要だと考えます。
Flutterの実装を読む
Flutterの3.29.0をベースに、各プラットフォームごとの実装をコードを見つつ整理します。
前提知識として必要なのは、FlutterのTextField
が生成されフォーカスを合わせると、TextInput
を介してネイティブのテキスト入力用オブジェクトにアクセスが行われるということです。
当然ではあるのですが、FlutterのTextField
は各プラットフォームのテキスト入力に関するAPIと直接やり取りできません。しかしパスワードマネージャーを呼び出すためには、各プラットフォームのお作法に則ってテキスト入力を制御する必要があります。
そのため、Flutterは各プラットフォームのテキスト入力用Widgetをラップし、いい感じに制御することで機能を実現しています。
iOSの実装
autocorrect
がfalse
の場合、autocorrectionとspell checkが無効になります。
前述の不具合があるため、設定についてのドキュメントを探したのですが、明確に組み合わせについて述べている箇所を見つけられませんでした。いくつかのクラスのドキュメントを合わせて眺めると、示唆が得られるかな…? といったところです。
Setting this property to true in any view that conforms to UITextInputTraits disables the user’s ability to copy the text in the view and, in some cases, also disables the user’s ability to record and broadcast the text in the view.
isSecureTextEntry
をセットすると、パスワード入力用のテキストフィールドになります。内部的に機能が制限され、文字の表示が*
に置き換わります。
The default value for this property is UITextSpellCheckingType.default, which enables spell-checking when autocorrection is also enabled.
スペルチェックはautocorrectionとセットの機能です。autocorrectionが無効な場合はスペルチェックも無効になります。
autofillHints
に関しては、AutofillHints.newUsername
以外はプラットフォームが定義する定数に変換されます。newUsername
については、動作しているっぽいので問題ないのかな…って感じです。react-nativeも見てみたのですが、イマイチわからなかったです。
Androidの実装
autocorrect
がtrue
の場合、InputType.TYPE_TEXT_FLAG_AUTO_CORRECTが設定されます。
iOSと異なり、spell checkの設定はautocorrect
と分離しています。筆者も今回調べていて知ったのですが、spellCheckConfiguration
を通して設定が行えるようです。
追加されたのはFlutter v3.7.0からでした。機能追加PRとrevert後にrelandされたPRがあります。
autofillHints
に関しては、autofillHints
に指定された値がそのままsetAutofillHints
で渡されます。
ここで渡している値は、Android 8.0(26)以降ではAutofill frameworkを利用するよう、文字列の変換がなされます。それ以前のバージョンでは、Flutterでセットした値がそのまま使われるようです。
定数の一覧は以下のリンクを参照してください。実際に利用される定数はViewに定義された定数なのですが、一覧性が非常に低いため、androidxの一覧を確認するのが良いはずです。
Webの実装
autocorrect
がtrue
の場合、autocorrect
属性がon
に設定されます。
MDNを見てみると、Firefox[3]とSafari[4]がサポートしています。2025年3月現在Chromeはサポートしていません。とはいえ、autocorrect
が仕様に反映されたPRを見てみると、Chromeにもサポートが入りそうな気配はあります。[5]
<input> elements, except for password, email, and url, which do not support autocorrection.
MDNのドキュメントによると、autocorrect
は<input>
要素に対して有効ですが、password
、email
、url
はサポートしていないとのことです。またautofillHints
にAutofillHints.password
やAutofillHints.newPassword
を指定する場合、<input>
要素はpassword
になります。このためパスワード用のTextField
ではautocorrect
は無効になります。
一方で、AutofillHints.username
は<input>
要素に対してtext
になります。このため、autocorrect
は有効にできます。
上記のコメントの通り、機能の実装時にはSafariのみがautocorrect
をサポートしていました。しかし他のブラウザが徐々にサポートに向けて動いているため、ある日を境にautocorrect
が利用されるかもしれません。
一方で、spellcheck
はFlutterがサポートする全てのブラウザがサポートしています。しかし未実装のようです。P2
なので、実装まではまだ時間がかかりそうです。
MDNのドキュメントは「sensitive informationを入力する場合には、spellcheck
をfalse
にすることを検討するべき」と述べています。
Using spellchecking can have consequences for users' security and privacy. The specification does not regulate how spellchecking is done and the content of the element may be sent to a third party for spellchecking results (see enhanced spellchecking and "spell-jacking").
You should consider setting spellcheck to false for elements that can contain sensitive information.
筆者の理解では、この"sensitive information"とはパスワードやクレジットカード情報などのことを指していると考えられます。AndroidやiOSの実装を見る限り、これらの情報を入力するTextField
に対するベストプラクティスが語られていないため、注意すべき文言のように感じます。
まとめ
autofillHints
とautocorrect
は、適切に組み合わせることでユーザーにとって良い体験を提供できます。autocorrect
はtrue
がデフォルト値ですが、autofillHints
を指定する場合にはfalse
に設定することを検討しましょう。
Discussion