Compose 中的自动填充

某些应用(例如密码管理工具)可以使用用户提供的数据来填充其他应用中的组件。填充其他应用组件的应用称为自动填充服务。自动填充框架负责管理应用与自动填充服务之间的通信。

填写凭据和表单是一项非常耗时且容易出错的任务。借助自动填充功能,用户可以节省填写字段的时间,并最大限度地减少用户输入错误。

只需几行代码,即可在 Compose 中实现自动填充功能。此功能可为用户带来以下好处:

填写凭据

借助自动填充功能,用户可以通过以下方式填充其凭据:

  • 当用户点按设置了自动填充语义的字段时,系统会向用户显示自动填充建议。
  • 系统会向用户显示自动填充建议,并根据用户输入的内容对其进行过滤。

保存凭据

用户可以通过以下方式通过自动填充功能保存凭据:

  • 系统会触发一个保存对话框,当用户向启用了自动填充功能的字段输入新信息或更新后的信息时,系统会提示用户保存信息。您可以通过以下两种方式进行保存:
    • 显式提交信息(例如,通过点击按钮)
    • 隐式:当用户离开页面时
  • 当某个字段设置了 ContentType.NewPassword 时,系统可能会向用户建议安全系数高的密码,具体取决于您的凭据提供程序。

您可以在应用中使用自动填充功能,为用户简化已保存数据的检索。自动填充功能通过 BasicTextField 支持文本组件,以及基于该组件的所有 Material 文本字段。

设置自动填充

在设备或模拟器上使用自动填充 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 参考文档

使用自动填充功能填充数据

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

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

每当用户离开屏幕时,系统都会调用 Commit。如果提交按钮已关联到导航,则无需调用提交。如果您仍希望点击 Submit 触发保存对话框,请在此处添加 Commit

用户点击该按钮后,会看到此底部动作条,提示他们将凭据保存到所选的凭据提供程序:

底部动作条提示用户保存密码。
图 3. 底部动作条提示用户保存密码。

通过建议安全系数高的密码使用自动填充功能节省流量

当您使用 NewUsernameNewPassword 内容类型时,用户可能会在键盘中看到一个用于建议安全系数高的密码的按钮,具体取决于您的凭据提供程序。用户点击此按钮后,系统会显示底部动作条,以便用户保存其凭据。您无需实现任何其他内容,用户便可获得此体验。

键盘工具栏中的“建议一个安全系数高的密码”条状标签。
图 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)