实现用户互动

Jetpack Compose 支持 Text 中的精细互动。文字选择现在更加灵活,并且可以跨各种可组合项布局进行选择。文字中的用户互动与其他可组合项布局不同,因为您无法为 Text 可组合项的某一部分添加修饰符。本页重点介绍支持用户互动的 API。

选择文本

默认情况下,可组合项不可选择,这意味着用户无法从应用中选择和复制文本。如需启用文本选择功能,请使用 SelectionContainer 可组合项封装文本元素:

@Composable
fun SelectableText() {
    SelectionContainer {
        Text("This text is selectable")
    }
}

用户选定了一个简短的文字段落。

您可能想为可选择区域的特定部分停用选择功能。如果要执行此操作,您需要使用 DisableSelection 可组合项来封装不可选择的部分:

@Composable
fun PartiallySelectableText() {
    SelectionContainer {
        Column {
            Text("This text is selectable")
            Text("This one too")
            Text("This one as well")
            DisableSelection {
                Text("But not this one")
                Text("Neither this one")
            }
            Text("But again, you can select this one")
            Text("And this one too")
        }
    }
}

一个较长的文字段落。用户尝试选中整个段落,但由于有两行内容应用了 DisableSelection,所以这两行无法选中。

获取文本的点击位置

如需监听 Text 的点击次数,您可以添加 clickable 修饰符。不过,如果您想在 Text 可组合项中获取点击位置,那么在针对文本的不同部分执行不同的操作时,您需要改用 ClickableText

@Composable
fun SimpleClickableText() {
    ClickableText(text = AnnotatedString("Click Me"), onClick = { offset ->
        Log.d("ClickableText", "$offset -th character is clicked.")
    })
}

点击注解

当用户点击 Text 可组合项时,您可能想向 Text 值的某一部分附加额外信息,例如向特定字词附加可在浏览器中打开的网址。如果要执行此操作,您需要附加一个注解,用于获取一个标记 (String)、一个项 (String) 和一个文字范围作为参数。在 AnnotatedString 中,这些注解可以按照其标记或文字范围进行过滤。示例如下:

@Composable
fun AnnotatedClickableText() {
    val annotatedText = buildAnnotatedString {
        append("Click ")

        // We attach this *URL* annotation to the following content
        // until `pop()` is called
        pushStringAnnotation(
            tag = "URL", annotation = "https://developer.android.com"
        )
        withStyle(
            style = SpanStyle(
                color = Color.Blue, fontWeight = FontWeight.Bold
            )
        ) {
            append("here")
        }

        pop()
    }

    ClickableText(text = annotatedText, onClick = { offset ->
        // We check if there is an *URL* annotation attached to the text
        // at the clicked position
        annotatedText.getStringAnnotations(
            tag = "URL", start = offset, end = offset
        ).firstOrNull()?.let { annotation ->
            // If yes, we log its value
            Log.d("Clicked URL", annotation.item)
        }
    })
}