🔍

[Flutter]Issueから考えるautofill+autocorrect問題

に公開

1行まとめ

FlutterのTextFieldTextFormFieldautofillHintsを指定する場合には、autocorrectfalseに設定しよう。


以下、詳細です。

autofillHintsautocorrect

TextFieldTextFormFieldには、autofillHintsプロパティとautocorrectプロパティがあります。これらは適切に組み合わせるべきプロパティです。不適切な組み合わせは、特定の環境で問題を引き起こす可能性があります。

https://api.flutter.dev/flutter/material/TextField-class.html

https://api.flutter.dev/flutter/material/TextFormField-class.html

この記事では、FlutterにおけるautofillHintsautocorrectの適切な指定について考察します。

autofillHints

https://api.flutter.dev/flutter/material/TextField/autofillHints.html

autofillHintsは入力フォームに自動入力するためのヒントを提供します。デフォルト値はnullです。

ユーザーにメールアドレスを入力してもらう場合、autofillHintsAutofillHints.emailを指定することで、自動入力の候補が表示されるようになります。意味合いとしてはkeyboardTypeと似ていますが、keyboardTypeはキーボードの種類を指定するのに対して、autofillHintsは自動入力のヒントを指定するという違いがあります。

FormAutofillGroupを組み合わせるケースが大半でしょう。たとえばAutofillHints.usernameAutofillHints.passwordによるログイン機能が典型例です。そのほか、クレジットカード情報であったり、住所情報であったりを自動入力できます。

ユーザービリティを高めることができるため、筆者のお気に入りの機能です。[1]

autocorrect

https://api.flutter.dev/flutter/material/TextField/autocorrect.html

autocorrectは、テキスト入力中に自動修正するかどうかを指定します。デフォルト値はtrueです。

調べてみると、この"correct"が何を意味するかは、Flutterが各プラットフォームのAPIをどの様に呼び出しているかに依存します。筆者が調べた範囲では、iOSでは自動修正とスペルチェックをセットで管理し、Androidでは自動修正のみを管理しているようです。Webはブラウザごとにサポート状況が異なっており、Safariの場合には言語によっては自動修正が行われるようです。

iOSのソフトウェアキーボードのパスワード欄がちらつく問題

https://github.com/flutter/flutter/issues/134723

iOS 17より、ソフトウェアキーボードのパスワード欄のちらつき問題が発生しています。

筆者の調査によると、この問題は「iOSのソフトウェアキーボードがパスワード欄を表示する際に、autocorrecttrueの場合に発生」します。このため、autocorrectfalseに設定することで問題を回避できます。

https://github.com/flutter/flutter/pull/165637

PRでは、パスワードマネージャーを呼び出す設定が有効な場合、autocorrectionTypespellCheckingTypeをNoに設定することで問題を回避しました。

https://developer.apple.com/documentation/uikit/uitextinputtraits/autocorrectiontype?language=objc

https://developer.apple.com/documentation/uikit/uitextinputtraits/spellcheckingtype?language=objc

この動作は、UIKitのUITextFieldを利用するケースでも同様のようです。FlutterはiOSのUITextFieldをラップしているため、このような問題が発生していると考えられます。PRに添付した再現するプロジェクトを添付したので、興味がある方は試してみてください。

なお、SwiftUIの場合はパスワードにSecureFieldを利用することでこの問題を回避できましたが、ユーザー名にTextFieldを利用する必要があるため回避できませんでした。詳しい方がいれば、どうするのがいいのかコメントいただけると助かります。

autocorrectは設定するべきなのか?

autocorrectのデフォルト値はtrueです。このため、autocorrectの設定を意識したことがない開発者も多いのではないかな、と思います。[2]

今一度「autocorrectを設定することは、ユーザーにとって便利なのか」を考えてみるのはいかがでしょうか。

筆者の個人的な経験になりますが、ユーザー名にautocorrectが設定されていたために、「正しいメールアドレスを入力したのに単語を修正された」ことがあります。具体的には(zennのアカウント名でもある)kojiを入力すると、kokiに修正されがちです。また、パスワードの入力欄にはautocorrectを設定するべきでないことは明らかです。もしもパスワードがautocorrectされてしまった場合、ユーザーが"正しくない"英単語を用いたパスワードを設定しにくくなってしまいます。

https://api.flutter.dev/flutter/services/AutofillHints-class.html

その他のケースを考えてみると、そもそもautofillHintsを設定するようなTextFieldautocorrectを設定するメリットがあるのか、という疑問が湧いてきます。見渡す限り、メリットよりもデメリットの方が上回るように感じます。

「ここはautocorrectされて欲しい」というTextFieldに対して、限定的にautocorrectを設定する方が、結果的にユーザーにとって良い体験になるのではないでしょうか。筆者はデフォルト値がtrueであることに疑問を感じています。とはいえ、この値が変わることはまずないため、開発者がautocorrectに注意を払うことが重要だと考えます。

Flutterの実装を読む

Flutterの3.29.0をベースに、各プラットフォームごとの実装をコードを見つつ整理します。

前提知識として必要なのは、FlutterのTextFieldが生成されフォーカスを合わせると、TextInputを介してネイティブのテキスト入力用オブジェクトにアクセスが行われるということです。

https://api.flutter.dev/flutter/services/TextInput-class.html

当然ではあるのですが、FlutterのTextFieldは各プラットフォームのテキスト入力に関するAPIと直接やり取りできません。しかしパスワードマネージャーを呼び出すためには、各プラットフォームのお作法に則ってテキスト入力を制御する必要があります。

そのため、Flutterは各プラットフォームのテキスト入力用Widgetをラップし、いい感じに制御することで機能を実現しています。

iOSの実装

autocorrectfalseの場合、autocorrectionとspell checkが無効になります。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm#L936-L941

前述の不具合があるため、設定についてのドキュメントを探したのですが、明確に組み合わせについて述べている箇所を見つけられませんでした。いくつかのクラスのドキュメントを合わせて眺めると、示唆が得られるかな…? といったところです。

https://developer.apple.com/documentation/uikit/uitextinputtraits/issecuretextentry

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をセットすると、パスワード入力用のテキストフィールドになります。内部的に機能が制限され、文字の表示が*に置き換わります。

https://developer.apple.com/documentation/uikit/uitextinputtraits/spellcheckingtype

The default value for this property is UITextSpellCheckingType.default, which enables spell-checking when autocorrection is also enabled.

スペルチェックはautocorrectionとセットの機能です。autocorrectionが無効な場合はスペルチェックも無効になります。

https://developer.apple.com/documentation/appkit/nstextcontenttype#Managing-accounts

autofillHintsに関しては、AutofillHints.newUsername以外はプラットフォームが定義する定数に変換されます。newUsernameについては、動作しているっぽいので問題ないのかな…って感じです。react-nativeも見てみたのですが、イマイチわからなかったです。

Androidの実装

autocorrecttrueの場合、InputType.TYPE_TEXT_FLAG_AUTO_CORRECTが設定されます。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java#L272

iOSと異なり、spell checkの設定はautocorrectと分離しています。筆者も今回調べていて知ったのですが、spellCheckConfigurationを通して設定が行えるようです。

https://api.flutter.dev/flutter/material/TextField/spellCheckConfiguration.html

追加されたのはFlutter v3.7.0からでした。機能追加PRrevert後にrelandされたPRがあります。


autofillHintsに関しては、autofillHintsに指定された値がそのままsetAutofillHintsで渡されます。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java#L789

ここで渡している値は、Android 8.0(26)以降ではAutofill frameworkを利用するよう、文字列の変換がなされます。それ以前のバージョンでは、Flutterでセットした値がそのまま使われるようです。

https://github.com/flutter/flutter/blob/f8c1f3cccca9e974658c90a3bae9c6250af2a690/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java#L546C29-L626

定数の一覧は以下のリンクを参照してください。実際に利用される定数はViewに定義された定数なのですが、一覧性が非常に低いため、androidxの一覧を確認するのが良いはずです。

https://developer.android.com/reference/androidx/autofill/HintConstants

Webの実装

autocorrecttrueの場合、autocorrect属性がonに設定されます。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart#L1350-L1351

MDNを見てみると、Firefox[3]とSafari[4]がサポートしています。2025年3月現在Chromeはサポートしていません。とはいえ、autocorrectが仕様に反映されたPRを見てみると、Chromeにもサポートが入りそうな気配はあります。[5]

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocorrect

<input> elements, except for password, email, and url, which do not support autocorrection.

MDNのドキュメントによると、autocorrect<input>要素に対して有効ですが、passwordemailurlはサポートしていないとのことです。またautofillHintsAutofillHints.passwordAutofillHints.newPasswordを指定する場合、<input>要素はpasswordになります。このためパスワード用のTextFieldではautocorrectは無効になります。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/autofill_hint.dart#L40-L44

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart#L513-L517

一方で、AutofillHints.username<input>要素に対してtextになります。このため、autocorrectは有効にできます。

https://github.com/flutter/flutter/blob/3.29.0/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart#L1060-L1067

上記のコメントの通り、機能の実装時にはSafariのみがautocorrectをサポートしていました。しかし他のブラウザが徐々にサポートに向けて動いているため、ある日を境にautocorrectが利用されるかもしれません。


https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck

一方で、spellcheckはFlutterがサポートする全てのブラウザがサポートしています。しかし未実装のようです。P2なので、実装まではまだ時間がかかりそうです。

https://github.com/flutter/flutter/issues/40682

MDNのドキュメントは「sensitive informationを入力する場合には、spellcheckfalseにすることを検討するべき」と述べています。

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck#security_and_privacy_concerns

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に対するベストプラクティスが語られていないため、注意すべき文言のように感じます。

まとめ

autofillHintsautocorrectは、適切に組み合わせることでユーザーにとって良い体験を提供できます。autocorrecttrueがデフォルト値ですが、autofillHintsを指定する場合にはfalseに設定することを検討しましょう。

脚注
  1. お気に入りなのでIssueを探しては解消する活動をしています ↩︎

  2. 筆者もその一人です ↩︎

  3. 2025年3月リリースのv136から ↩︎

  4. もともとSafariの独自仕様だったらしい ↩︎

  5. https://github.com/whatwg/html/pull/5841 ↩︎

GitHubで編集を提案

Discussion