パスワード マネージャーなどのアプリを利用すると、別のアプリのコンポーネントにおいて、ユーザーが入力したデータを次回以降もそのまま入力できます。このように別のアプリに対して入力を行うアプリは、「自動入力サービス」と呼ばれます。自動入力フレームワークは、アプリと自動入力サービス間の通信を管理します。
認証情報やフォームの入力は時間がかかる作業であり、ミスが発生する可能性があります。自動入力を使用すると、項目に入力する時間を省き、ユーザー入力ミスを最小限に抑えることができます。
数行のコードだけで、Compose で自動入力を実装できます。この機能には、ユーザーにとって次のようなメリットがあります。
認証情報を入力する
自動入力では、ユーザーは次の方法で認証情報を入力できます。
- 自動入力のセマンティクスが設定されているフィールドをタップすると、自動入力の候補が表示されます。
- システムは、ユーザーに自動入力候補を表示し、ユーザーが入力した内容に基づいて候補をフィルタします。
認証情報を保存する
ユーザーは、自動入力を使用して次の方法で認証情報を保存できます。
- 自動入力が有効になっているフィールドに新しい情報や更新された情報を入力すると、システムによって保存ダイアログがトリガーされ、情報の保存を求めるメッセージがユーザーに表示されます。保存は次の 2 つの方法で行うことができます。
- 明示的に(ボタンをクリックするなどして情報をコミットする)
- ユーザーがページから移動したとき(暗黙的)
- 認証情報プロバイダによっては、フィールドに
ContentType.NewPassword
が設定されている場合、システムがユーザーに強力なパスワードを提案することがあります。
アプリで自動入力を使用すると、ユーザーが保存したデータを簡単に取得できます。自動入力は、BasicTextField
を介したテキスト コンポーネントと、そのコンポーネントをベースに構築されたすべてのマテリアル テキスト フィールドをサポートします。
自動入力を設定
デバイスまたはエミュレータで自動入力 API を使用する前に、[設定] で自動入力を有効にする必要があります。ここで、自動入力の認証情報プロバイダを指定して、認証情報を保存できます。

コンテンツ タイプを使用してテキスト フィールドに自動入力を追加する
TextField
が自動入力に対応していることを示すには、フィールドが受け入れ可能な型で ContentType
セマンティクスを設定します。これは、この特定のフィールドに関連する可能性のあるユーザーデータの種類を自動入力サービスに示します。ContentType.Username
を使用して、ユーザーがユーザー名を入力できる TextField
を設定します。
ContentType
セマンティクスを設定すると、ユーザーはデバイスの認証情報プロバイダにすでに保存されている自動入力情報にアクセスできます。たとえば、ユーザーがノートパソコンの Chrome ブラウザでアプリにログインし、認証情報プロバイダでパスワードを保存している場合、自動入力によって認証情報が提供されます。
値ベースのテキスト フィールド
TextField( value = textFieldValue.value, onValueChange = {textFieldValue.value = it}, modifier = Modifier.semantics { contentType = ContentType.Username } )
状態ベースのテキスト フィールド
TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.Username } )
複数のタイプの自動入力フィールドを追加する
場合によっては、TextField
が複数の ContentType
を受け取るようにしたいことがあります。たとえば、ログイン フィールドでメールアドレスまたはユーザー名のいずれかを入力できる場合があります。+
演算子を使用すると、TextField
に複数のコンテンツ タイプを追加できます。
自動入力で保存できるすべてのデータタイプについては、ContentType
リファレンスをご覧ください。
値ベースのテキスト フィールド
TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.Username + ContentType.EmailAddress } )
状態ベースのテキスト フィールド
TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.Username + ContentType.EmailAddress } )
自動入力でデータを入力する
TextField
に ContentType
を追加すると、ユーザーが認証情報を入力できるようになります。
ユーザーが自動入力が有効になっているフィールドをクリックすると、関連するデータが保存されている場合は、キーボードの上にあるツールバーに、認証情報を入力するよう求めるチップが表示されます。

ナビゲーションによる自動入力でデータを保存する
Compose は、ユーザーがページから移動して入力した認証情報を commit するタイミングを自動的に判断しようとします。フィールドで自動入力が有効になると、ユーザーがページから移動したときに、追加のコードを必要とせずに認証情報が自動的に保存されます。
自動入力でデータを明示的に保存する
自動入力を使用してテキスト フィールド経由で新しい認証情報を明示的に保存するには、自動入力マネージャーによって自動入力コンテキストがコミット(またはキャンセル)される必要があります。ローカルの自動入力マネージャーは、必要に応じて自動入力フレームワークと通信します。ユーザーが入力した認証情報を削除する場合は、AutofillManager.cancel
を呼び出して、保留中のデータを保存せずに削除します。
次のスニペットは、ボタンを使用して自動入力でデータを明示的に保存する方法を示しています。
Autofill マネージャーを保持するローカル変数を作成します。これは次のように取得できます。
val autofillManager = LocalAutofillManager.current
TextField(s)
で、Modifier.semantics
を使用して選択したコンテンツ タイプを追加します。値ベースのテキスト フィールドの場合:
val autofillManager = LocalAutofillManager.current Column { TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.NewUsername } ) Spacer(modifier = Modifier.height(16.dp)) TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.NewPassword } ) }
状態ベースのテキスト フィールドの場合:
val autofillManager = LocalAutofillManager.current Column { TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.NewUsername } ) Spacer(modifier = Modifier.height(16.dp)) TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.NewPassword } ) }
必要に応じて、ボタンをクリックして自動入力コンテキストをコミットします。
値ベースのテキスト フィールドの場合:
val autofillManager = LocalAutofillManager.current Column { TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.NewUsername }, ) Spacer(modifier = Modifier.height(16.dp)) TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.NewPassword }, ) // Submit button Button(onClick = { autofillManager?.commit() }) { Text("Reset credentials") } }
状態ベースのテキスト フィールドの場合:
val autofillManager = LocalAutofillManager.current Column { TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.NewUsername }, ) Spacer(modifier = Modifier.height(16.dp)) TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.NewPassword }, ) // Submit button Button(onClick = { autofillManager?.commit() }) { Text("Reset credentials") } }
Commit は、ユーザーが画面から移動するたびに呼び出されます。送信ボタンがナビゲーションにリンクされている場合、Commit を呼び出す必要はありません。[送信] をクリックしたときに保存ダイアログをトリガーしたい場合は、ここに Commit を追加します。
ユーザーがボタンをクリックすると、選択した認証情報プロバイダに認証情報を保存するよう求めるボトムシートが表示されます。

安全なパスワードの候補の表示による自動入力でデータを保存する
認証情報プロバイダによっては、NewUsername
と NewPassword
のコンテンツ タイプを使用しているときに、キーボードに [強力なパスワードを提案] ボタンが表示されることがあります。このボタンをクリックすると、ボトムシートが表示され、認証情報を保存できます。ユーザーがこのエクスペリエンスを利用するために、他に実装する必要はありません。


トラブルシューティング
「保存」のユーザー ジャーニーを呼び出す際に、[今はしない] を複数回クリックすると、認証情報プロバイダがボトムシートを表示しなくなることがあります。再度有効にして表示させるには、[パスワードを保存しますか?] をブロックしている特定のアプリを削除する必要があります。

自動入力をさらにカスタマイズする
自動入力の一般的なユーザー ジャーニーでは、自動入力が有効なコンポーネントに認証情報が入力されると、そのコンポーネントの色が変わり、ハイライト表示されます。これは、自動入力が正常に完了したことをユーザーに知らせるためです。
このハイライトの色をカスタマイズするには、CompositionLocal
を使用して、任意の色を指定します。デフォルトの自動入力ハイライト表示の色は Color(0x4dffeb3b)
として定義されています。
値に基づくテキスト フィールド
val customHighlightColor = Color.Red CompositionLocalProvider(LocalAutofillHighlightColor provides customHighlightColor) { TextField( value = textFieldValue.value, onValueChange = { textFieldValue.value = it }, modifier = Modifier.semantics { contentType = ContentType.Username } ) }
状態ベースのテキスト フィールド
val customHighlightColor = Color.Red CompositionLocalProvider(LocalAutofillHighlightColor provides customHighlightColor) { TextField( state = rememberTextFieldState(), modifier = Modifier.semantics { contentType = ContentType.Username } ) }