Compose での自動入力

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

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

数行のコードだけで、Compose に自動入力を実装できます。この機能は、ユーザーに次のような特典をもたらします。

認証情報を入力する

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

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

認証情報を保存する

自動入力を使用して認証情報を保存するには、次の方法があります。

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

アプリで自動入力を使用すると、保存されたデータを簡単に取得できます。自動入力は、 BasicTextField を介したテキスト コンポーネントと、そのコンポーネントを基盤とするすべてのマテリアル テキスト フィールドをサポートしています。

自動入力を設定する

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

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

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

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

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

TextFieldContentType を追加すると、ユーザーが認証情報を入力できるようになります。

自動入力が有効になっているフィールドをクリックすると、関連するデータが保存されている場合は、キーボードの上にあるツールバーにチップが表示され、認証情報の入力を促されます。

テキスト ツールバーに保存された認証情報が表示されているチップ。
図 2.保存された 認証情報を示すテキスト ツールバーのチップ。

ナビゲーションを使用して自動入力でデータを保存する

Compose は、ユーザーがページから移動して入力した認証情報を確定するタイミングを自動的に判断しようとします。フィールドが自動入力に対応している場合、追加のコードを記述しなくても、ユーザーがページから移動すると認証情報が自動的に保存されます。

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

自動入力を使用してテキスト フィールドから新しい認証情報を明示的に保存するには、自動入力マネージャーによって自動入力コンテキストを確定(またはキャンセル)する必要があります。ローカルの自動入力マネージャーは、必要に応じて自動入力フレームワークと通信します。ユーザーが入力した認証情報を削除する場合は、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 }
          )
      }

    • 状態ベースのテキスト フィールドの場合:

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

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

    • 値ベースのテキスト フィールドの場合:

      val autofillManager = LocalAutofillManager.current
      
      Column {
          TextField(
              value = usernameTextFieldValue.value,
              onValueChange = { usernameTextFieldValue.value = it },
              modifier = Modifier.semantics { contentType = ContentType.NewUsername },
          )
      
          Spacer(modifier = Modifier.height(16.dp))
      
          TextField(
              value = passwordTextFieldValue.value,
              onValueChange = { passwordTextFieldValue.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 を追加します。

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

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

[安全なパスワードを自動生成] を使用して自動入力でデータを保存する

認証情報プロバイダによっては、NewUsernameNewPassword コンテンツ タイプを使用している場合に、キーボードに [**安全なパスワードを自動生成**] ボタンが表示されることがあります。このボタンをクリックすると、認証情報を保存できるボトムシートが表示されます。ユーザーがこの操作を行えるようにするために、他に実装する必要はありません。

キーボード ツールバーの [安全なパスワードを自動生成] チップ。
図 4.キーボード ツールバーの [安全なパスワードを自動生成] チップ。
安全なパスワードの使用を促すボトムシート。
図 5.安全なパスワードの使用を促すボトムシート。

トラブルシューティング

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

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

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

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

このハイライトの色をカスタマイズするには、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 }
    )
}