3. 可点击文本链接样式

可点击文本链接样式 学习卡片

ClickableText 与 Modifier.clickable 的差异

在 Compose 中为文本添加点击事件有两条路径:ClickableText 是专门为文本设计的可组合项,它把点击位置映射为字符偏移量(offset),适合需要知道"用户点了哪个字"的场景;Modifier.clickable 则把整段文本当作一个整体点击区域,适合"整行文字即一个链接"的简单交互。两者在回调参数、点击粒度、视觉反馈上都有明显区别。

ClickableText 点击位置 → 字符偏移量 访问官网 查看文档 联系我们 0 4 9 14 onClick: (Int) → Unit offset 落在哪个区间,就触发 对应链接的回调 offset 判断逻辑 offset in 0..3 → 官网 offset in 4..8 → 文档 Modifier.clickable 整段文本 → 一个点击区域 访问官网 查看文档 联系我们 整个矩形区域均可点击 onClick: () → Unit 无位置参数,只关心"被点了" 适合整行跳转或展开 视觉反馈 默认带涟漪(indication) 可配合 interactionSource 自定义 对比

ClickableText 实现多链接文本

下面这段代码把一段包含两个链接的文本渲染出来,点击"官网"和"文档"分别触发不同回调。关键点在于用 AnnotatedString 标记链接区间,再在 onClick 中根据 offset 判断落在哪个区间。

@Composable
fun MultiLinkText() {
    val linkColor = Color(0xFF1A73E8)
    val annotated = buildAnnotatedString {
        append("访问 ")
        withStyle(SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline)) {
            pushStringAnnotation(tag = "URL", annotation = "https://example.com")
            append("官网")
            pop()
        }
        append(" 或查看 ")
        withStyle(SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline)) {
            pushStringAnnotation(tag = "URL", annotation = "https://docs.example.com")
            append("文档")
            pop()
        }
        append(" 了解更多。")
    }

    ClickableText(
        text = annotated,
        style = TextStyle(fontSize = 16.sp, color = Color(0xFF333333)),
        onClick = { offset ->
            annotated.getStringAnnotations(tag = "URL", start = offset, end = offset)
                .firstOrNull()?.let { annotation ->
                    // 此处处理点击回调,例如打开浏览器或更新状态
                    println("点击链接: ${annotation.item}")
                }
        }
    )
}
offset 边界注意:当点击位置恰好落在两个链接之间的空白字符上时,getStringAnnotations 返回空列表,此时不应触发任何链接回调。建议在 let 之前先判断结果是否为空,避免误触。

Modifier.clickable 实现整行链接

如果整段文本就是一个链接,用 Modifier.clickable 更简洁,而且自带涟漪反馈。注意 clickable 需要配合 indication 和 interactionSource 才能获得默认涟漪效果(在 Material3 中通常由 Modifier.clickable 的默认参数提供)。

@Composable
fun WholeLineLink(onClick: () -> Unit) {
    Text(
        text = "查看完整文档 →",
        color = Color(0xFF1A73E8),
        textDecoration = TextDecoration.Underline,
        fontSize = 16.sp,
        modifier = Modifier
            .clickable { onClick() }
            .padding(vertical = 8.dp, horizontal = 4.dp)
    )
}

两种方式的选择依据

判断维度ClickableTextModifier.clickable
点击粒度字符级(offset)整体区域
回调参数(Int) → Unit() → Unit
多链接支持原生支持,需手动判断区间需拆成多个 Text 组合
涟漪反馈无默认涟漪默认带涟漪
适用场景富文本内嵌多个链接整行/整块文字作为单一链接
常见问题:使用 ClickableText 时如果忘记在 onClick 中做 offset 区间判断,会导致点击任意位置都触发同一个回调。务必用 getStringAnnotations 或手动比较 offset 范围来区分不同链接。