如何在Jetpack Compose中实现指定下划线文本可点击?
解决仅让下划线协议文本可点击的问题
要实现只有下划线的协议文本可点击,需要替换普通Text为ClickableText,并给每个下划线文本段添加标注来区分点击区域,具体修改如下:
1. 更新调用处的回调参数
把原来的单一回调拆分为两个,分别对应两个下划线文本的点击逻辑:
CheckedBox( modifier = Modifier, fontSize = 14.sp, underlineText1 = "Çerez politikası'nı", staticText1 = " ve", underlineText2 = " kişisel verilerin korunması kanunu'nu ", staticText2 = "okudum ve anladım", onUnderlineText1Click = { // 这里写展示Cookie政策的逻辑 }, onUnderlineText2Click = { // 这里写展示个人数据保护法的逻辑 } ) CheckedBox( modifier = Modifier, fontSize = 14.sp, underlineText1 = "Kullanıcı sözleşmesi'ni ", staticText1 = " ve gizlilik politikasını okudum, anladım ve kabul ediyorum", underlineText2 = null, staticText2 = null, onUnderlineText1Click = { // 这里写展示用户协议的逻辑 }, onUnderlineText2Click = {} // 第二个下划线文本为空,空实现即可 )
2. 修改CheckedBox组件实现
替换普通Text为ClickableText,并给下划线文本添加标注来识别点击区域:
@Composable fun CheckedBox( modifier: Modifier, underlineText1: String, fontSize: TextUnit, staticText1: String, underlineText2: String?, staticText2: String?, onUnderlineText1Click: () -> Unit, onUnderlineText2Click: () -> Unit ) { val isCheck = remember { mutableStateOf(false) } val color = if (isSystemInDarkTheme()) Color(0xFF1A1818) else Color.White val annotatedText = buildAnnotatedString { // 给第一个下划线文本添加标注 appendAnnotation(tag = "UNDERLINE_TEXT_1", annotation = "click") withStyle( style = SpanStyle( textDecoration = TextDecoration.Underline, fontSize = fontSize ) ) { append(underlineText1) } appendAnnotation(tag = "UNDERLINE_TEXT_1", annotation = "end") // 静态文本1 withStyle(style = SpanStyle(fontSize = fontSize)) { append(staticText1) } underlineText2?.let { text2 -> staticText2?.let { static2 -> // 给第二个下划线文本添加标注 appendAnnotation(tag = "UNDERLINE_TEXT_2", annotation = "click") withStyle( style = SpanStyle( textDecoration = TextDecoration.Underline, fontSize = fontSize ) ) { append(text2) } appendAnnotation(tag = "UNDERLINE_TEXT_2", annotation = "end") // 静态文本2 withStyle(style = SpanStyle(fontSize = fontSize)) { append(static2) } } } } Row( modifier = Modifier .fillMaxWidth() .padding(start = 15.dp, end = 15.dp, top = 10.dp, bottom = 10.dp) ) { Card( elevation = 0.dp, shape = RoundedCornerShape(6.dp), border = BorderStroke(2.dp, color = MaterialTheme.colors.grayColor) ) { Box( modifier = Modifier .size(25.dp) .weight(1f) .background(if (isCheck.value) DYTGreenColor else color) .clickable { isCheck.value = !isCheck.value }, contentAlignment = Alignment.TopStart ) { if (isCheck.value) Icon(Icons.Default.Check, contentDescription = "", tint = Color.White) } } // 使用ClickableText替代普通Text ClickableText( modifier = Modifier.padding(start = 10.dp), text = annotatedText, onClick = { offset -> // 检查点击位置是否属于第一个下划线文本 annotatedText.getStringAnnotations( tag = "UNDERLINE_TEXT_1", start = offset, end = offset ).firstOrNull()?.let { onUnderlineText1Click() } // 检查点击位置是否属于第二个下划线文本 annotatedText.getStringAnnotations( tag = "UNDERLINE_TEXT_2", start = offset, end = offset ).firstOrNull()?.let { onUnderlineText2Click() } } ) } }
关键说明
- 用
appendAnnotation为每个下划线文本添加专属标记,标记的作用是让ClickableText识别点击区域 - 替换成
ClickableText后,通过getStringAnnotations判断点击位置是否落在某个下划线文本的范围内,从而触发对应的展示逻辑 - 拆分回调函数后,每个下划线文本的点击逻辑可以独立实现,互不干扰
内容的提问来源于stack exchange,提问作者NewPartizal
相关产品推荐
相关产品推荐

