Compose 中的自動填入功能

密碼管理工具等應用程式可以將使用者提供的資料,填入其他應用程式的元件。這類將資料填入其他應用程式元件的應用程式,通稱為「自動填入服務」。自動填入架構會管理應用程式和自動填入服務之間的通訊。

填寫憑證和表單是耗時又容易出錯的工作。 自動填入功能可讓使用者節省填寫欄位的時間,並減少輸入錯誤。

您只需幾行程式碼,就能在 Compose 中實作自動填入功能。這項功能可為使用者帶來以下好處:

填寫憑證

使用者可以透過下列方式,使用自動填入功能填寫憑證:

  • 使用者輕觸已設定自動填入語意的欄位時,系統會顯示自動填入建議。
  • 系統會向使用者顯示自動填入建議,並根據使用者輸入的內容篩選建議。

儲存憑證

使用者可以透過下列方式,透過自動填入功能儲存憑證:

  • 當使用者在啟用自動填入功能的欄位中輸入新資訊或更新資訊時,系統會觸發儲存對話方塊,提示使用者儲存資訊。儲存方式有兩種:
    • 明確提交資訊 (例如點選按鈕)
    • 隱含:使用者離開網頁時
  • 視憑證供應商而定,如果欄位已設定 ContentType.NewPassword,系統可能會向使用者建議高強度密碼。

您可以在應用程式中使用自動填入功能,簡化使用者擷取已儲存資料的流程。自動填入功能支援透過 BasicTextField 建立的文字元件,以及所有以該元件為基礎的 Material 文字欄位。

設定自動填入功能

在裝置或模擬器上使用自動填入 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
    }
)

使用自動填入功能填入資料

TextField 中新增 ContentType 後,使用者就能填寫憑證,不需執行任何其他步驟。

使用者點選啟用自動填入功能的欄位時,如果系統儲存了相關資料,鍵盤上方的工具列就會顯示晶片,提示使用者填入憑證。

文字工具列中的方塊顯示已儲存的憑證。
圖 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 = 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」

使用者點選按鈕後,系統會顯示這份底部功能表,提示他們將憑證儲存至所選憑證供應商:

底部功能表提示使用者儲存密碼。
圖 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 }
    )
}