部分着色文本并使其在Jetpack Compose中可点击

17
在XML中声明的视图中,我们可以使用SpannableStringBuilder来对部分字符串进行着色,就像这里提到的那样https://dev59.com/qG445IYBdhLWcg3wXZIy#4897412
但是在JetPack Compose中,我无法仅通过单个Text实现相同的效果。
我想要类似于这样的效果。

Partial color text

如您所见,只有“注册”文本的颜色不同,而且我希望它可以被点击。这是目前我的文本代码的样子。
Text(text = "Don't have an account? Sign Up",
                        modifier = Modifier.align(Alignment.BottomCenter),
                        style = MaterialTheme.typography.h6,
                        color = MaterialTheme.colors.secondary,
                    )

这在Jetpack Compose中是否可能?

1
对于单独的颜色方面,您需要使用“AnnotatedString”。我不知道是否有办法使该段可点击。 - CommonsWare
@CommonsWare 是的,就是那样。谢谢您指引我正确的方向。 - Mayur Gajra
1个回答

26
所以在@CommonsWare的评论和Compose文档的帮助下,我成功地使用AnnotatedStringClickableText创建了相同的效果。为了让任何人都能理解,我在内联中添加了注释。
@Composable
fun AnnotatedClickableText() {
    val annotatedText = buildAnnotatedString {
        //append your initial text
        withStyle(
            style = SpanStyle(
                color = Color.Gray,
            )
        ) {
            append("Don't have an account? ")

        }

        //Start of the pushing annotation which you want to color and make them clickable later
        pushStringAnnotation(
            tag = "SignUp",// provide tag which will then be provided when you click the text
            annotation = "SignUp"
        )
        //add text with your different color/style
        withStyle(
            style = SpanStyle(
                color = Color.Red,
            )
        ) {
            append("Sign Up")
        }
        // when pop is called it means the end of annotation with current tag
        pop()
    }

    ClickableText(
        text = annotatedText,
        onClick = { offset ->
            annotatedText.getStringAnnotations(
                tag = "SignUp",// tag which you used in the buildAnnotatedString
                start = offset,
                end = offset
            )[0].let { annotation ->
                //do your stuff when it gets clicked
                Log.d("Clicked", annotation.item)
            }
        }
    )
}

10
感谢提供这个示例。目前,如果没有标签点击文本会抛出 java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 的异常。若要纠正此问题,请按照此文档中所示的方法,并使用 .firstOrNull()?.let { annotation} - kelvin
感谢您在“pop()”“当前标签”上方的评论。当我使用多个推送时,我遇到了一个问题,无论我点击什么,它都只触发第一个推送的项目。 - adwardwo1f
使用.forEach来处理多个注释,而不是[0].let。 - Sean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接