Compose での自動入力

パスワード マネージャーなどのアプリを利用すると、別のアプリのコンポーネントにおいて、ユーザーが入力したデータを次回以降もそのまま入力できます。このように別のアプリに対して入力を行うアプリは、「自動入力サービス」と呼ばれます。自動入力フレームワークは、アプリと自動入力サービス間の通信を管理します。

認証情報とフォームの入力は時間がかかる作業であり、ミスが発生する可能性があります。自動入力を使用すると、ユーザーは項目に入力する時間を省き、ユーザー入力ミスを最小限に抑えることができます。

Compose で自動入力を実装するには、数行のコードのみで済みます。この機能には、ユーザーにとって次のようなメリットがあります。

認証情報を入力する

自動入力では、ユーザーは次の方法で認証情報を入力できます。

  • 自動入力セマンティクスが設定されているフィールドをタップすると、自動入力の候補がユーザーに表示されます。
  • システムは自動入力の候補をユーザーに表示し、ユーザーが入力した内容に基づいて候補をフィルタします。

認証情報を保存する

ユーザーは、次の方法で自動入力を使用して認証情報を保存できます。

  • 自動入力が有効になっているフィールドに新しい情報または更新された情報を入力すると、保存ダイアログがトリガーされ、ユーザーに情報を保存するよう求めるメッセージが表示されます。保存は次の 2 つの方法で行えます。
    • 明示的に、情報を commit する(ボタンのクリックなど)
    • 暗黙的に、ユーザーがページから移動したとき
  • 認証情報プロバイダによっては、フィールドに ContentType.NewPassword が設定されている場合に、システムが強力なパスワードをユーザーに提案することがあります。

アプリで自動入力を使用すると、ユーザーの保存済みデータの取得を効率化できます。自動入力は、BasicTextField を介したテキスト コンポーネントと、そのコンポーネント上に構築されたすべてのマテリアル テキスト フィールドをサポートしています。

自動入力を設定

デバイスまたはエミュレータで Autofill API を使用する前に、[設定] で自動入力を有効にする必要があります。ここで、自動入力で認証情報を保存する認証情報プロバイダを指定できます。

認証情報プロバイダを指定する方法を示す設定ページ。
図 1. 認証情報プロバイダを指定する方法を示す設定ページ。

コンテンツ タイプを使用してテキスト フィールドに自動入力を追加する

TextField が自動入力対応であることを示すには、フィールドで受け入れることができる型を使用して ContentType セマンティクスを設定します。これにより、この特定のフィールドに関連する可能性のあるユーザーデータの種類が自動入力サービスに示されます。ContentType.Username を使用して、ユーザーがユーザー名を入力できる TextField を設定します。

TextField(
    value = textFieldValue.value,
    onValueChange = {textFieldValue.value = it},
    modifier = Modifier.semantics { contentType = ContentType.Username }
)

ContentType セマンティクスを設定すると、ユーザーはデバイスの認証情報プロバイダにすでに保存されている自動入力情報にアクセスできます。たとえば、ユーザーがラップトップの Chrome ブラウザからアプリにログインし、認証情報プロバイダを通じてパスワードを保存している場合、その認証情報は自動入力によって提供されます。

複数のタイプを持つ自動入力フィールドを追加する

場合によっては、TextField に複数の ContentType を割り当てる必要があります。たとえば、ログイン フィールドではメールアドレスまたはユーザー名を指定できます。+ 演算子を使用して、複数のコンテンツ タイプを TextField に追加できます。

TextField(
    value = textFieldValue.value,
    onValueChange = { textFieldValue.value = it },
    modifier = Modifier.semantics {
        contentType = ContentType.Username + ContentType.EmailAddress
    }
)

自動入力で保存できるデータの種類については、ContentTypeリファレンスをご覧ください。

自動入力でデータを入力する

TextFieldContentType を追加すると、ユーザーが認証情報を入力できるようにするために他に何もする必要はありません。

ユーザーが自動入力対応のフィールドをクリックすると、関連するデータが保存されている場合は、キーボード上部のツールバーにチップが表示され、認証情報を入力するよう求められます。

保存した認証情報を示すテキスト ツールバーのチップ。
図 2. 保存した認証情報を示すテキスト ツールバーのチップ。

ナビゲーションによる自動入力でデータを節約する

Compose は、ユーザーがページから移動したときに入力された認証情報を自動的に検出して commit します。フィールドで自動入力を有効にすると、ユーザーがページから移動したときに、追加のコードを必要とせずに認証情報が自動的に保存されます。

自動入力で明示的にデータを保存する

自動入力を使用してテキスト フィールドから新しい認証情報を明示的に保存するには、自動入力マネージャーによって自動入力コンテキストが commit される(またはキャンセルされる)必要があります。ローカル自動入力マネージャーは、必要に応じて自動入力フレームワークと通信します。ユーザーが入力した認証情報を削除する場合は、AutofillManager.cancel を呼び出して、保留中のデータを保存せずに削除します。

次のスニペットは、ボタンを使用して自動入力でデータを明示的に保存する方法を示しています。

  1. 自動入力マネージャーを保持するローカル変数を作成します。この変数は、次の方法で取得できます。

    val autofillManager = LocalAutofillManager.current

  2. 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 }
        )
    }

  3. 必要に応じて、ボタンのクリックで自動入力コンテキストを commit します。

    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") }
    }

Commit は、ユーザーが画面から離れるたびに呼び出されます。[送信] ボタンがナビゲーションにリンクされている場合は、Commit を呼び出す必要はありません。[送信] をクリックして保存ダイアログをトリガーする場合は、ここに [Commit] を追加します。

ユーザーがボタンをクリックすると、選択した認証情報プロバイダに認証情報を保存するよう求めるボトムシートが表示されます。

パスワードを保存するようユーザーに促すボトムシート。
図 3. パスワードの保存を促すボトムシート。

安全なパスワードの候補を表示して自動入力でデータを保存する

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

キーボード ツールバーの安全なパスワードの候補チップ。
図 4. キーボード ツールバーの安全なパスワードの候補チップ。
安全なパスワードを使用するようユーザーに促すボトムシート。
図 5. 安全なパスワードを使用するようユーザーに促すボトムシート。

トラブルシューティング

「保存」ユーザー ジャーニーを呼び出すときに [後で] を複数回クリックすると、認証情報プロバイダの下部シートが表示されなくなることがあります。この機能を再度有効にして表示するには、[このパスワードを記憶する] をブロックしている特定のアプリを削除する必要があります。

パスワードを保存するようユーザーに促すボトムシート。
図 6. パスワードを保存するようユーザーに求めるボトムシート。

自動入力をさらにカスタマイズする

自動入力の一般的なユーザー ジャーニーでは、自動入力対応コンポーネントに認証情報が入力されると、色が変わりハイライト表示され、自動入力が正常に完了したことをユーザーに知らせます。

このハイライト色をカスタマイズするには、CompositionLocal を使用して、任意の色を指定します。

val customHighlightColor = Color.Red

CompositionLocalProvider(LocalAutofillHighlightColor provides customHighlightColor) {
    TextField(
        value = textFieldValue.value,
        onValueChange = { textFieldValue.value = it },
        modifier = Modifier.semantics { contentType = ContentType.Username }
    )
}

デフォルトの自動入力ハイライトの色は Color(0x4dffeb3b) として定義されています。