如何使可点击文本对屏幕阅读器可访问

3
这段代码在Jetpack Compose Composable中创建了一个ClickableText元素:
ClickableText(
  text = forgotPasswordAnnotatedString,
  onClick = {
  context.startActivity(intent)
},
  modifier = Modifier
    .padding(top = mediumPadding)
)

这里定义了带注释的字符串,目的是让文本看起来像一个链接:

val forgotPasswordAnnotatedString = buildAnnotatedString {
    append(stringResource(R.string.forgot_password))
    addStyle(
        style = SpanStyle(
            textDecoration = TextDecoration.Underline,
            color = Color.White,
            fontSize = 16.sp,
            fontWeight = FontWeight.Medium
        ),
        start = 0,
        end = 21,
    )
}

当我在安卓使用TalkBalk屏幕阅读器时,它没有明确表明这是可点击的文本,只是朗读了文本。有没有办法让屏幕阅读器清楚地知道这是可交互的文本?否则,我应该使用一个按钮并将其样式设计成链接吗?

1
使用TextButton。 - Gabriele Mariotti
2个回答

3
看起来你的意图是让整个文本都可点击?那么你最好的选择可能是一个TextButton,就像Gabriele Mariotti建议的那样。
但是,如果你只想让部分链接可点击,或者有多个可点击区域,我能想到的最好方法是在文本上方绘制一个不可见的框。这意味着我可以控制可点击区域的触摸目标至少为48.dp,并可以使用semantics{}修饰符来控制屏幕阅读器的解释方式。
欢迎任何建议。
// remember variables to hold the start and end position of the clickable text
val startX = remember { mutableStateOf(0f) }
val endX = remember { mutableStateOf(0f) }
// convert to Dp and work out width of button
val buttonPaddingX = with(LocalDensity.current) { startX.value.toDp() }
val buttonWidth = with(LocalDensity.current) { (endX.value - startX.value).toDp() }

Text(
    text = forgotPasswordAnnotatedString,
    onTextLayout = {
        startX.value = it.getBoundingBox(0).left // where 0 is the start index of the range you want to be clickable
        endX.value = it.getBoundingBox(21 - 1).right // where 21 is the end index of the range you want to be clickable
    }
)

请注意,buttonPaddingX是相对于文本位置而不是窗口的,因此您可能需要在Box {}中同时包围它们或使用ConstraintLayout。
然后绘制不可见的框。
Box(modifier = Modifier
    .sizeIn(minWidth = 48.dp, minHeight = 48.dp) // minimum touch target size
    .padding(start = buttonPaddingX)
    .width(buttonWidth)
    //  .background(Color.Magenta.copy(alpha = 0.5f)) // uncomment this to debug where the box is drawn
    .clickable(onClick = { context.startActivity(intent) })
    .semantics {
        // tell TalkBack whatever you need to here
        role = Role.Button
        contentDescription = "Insert button description here"
    }
)

在我的代码中,我使用pushStringAnnotation(TAG, annotation)而不是直接引用字符串索引。这样我就可以通过annotatedString.getStringAnnotations(TAG,0,annotatedString.length).first()获取可点击区域的起始和结束索引。如果文本中有多个链接,这将非常有用。

令人失望的是,ClickableText从一开始就没有考虑无障碍性,希望我们能在将来的更新中再次使用它。


1
将.semantics.contentDescription添加到修改器中可以更改屏幕阅读器读取的内容。我必须用contentDescription这个词来表明这是一个重置密码的链接。
屏幕阅读器仍然无法识别该元素为可点击,但希望描述对用户传达此元素是交互式的会有帮助。
ClickableText(
      text = forgotPasswordAnnotatedString,
      onClick = {
          context.startActivity(intent)
      },
      modifier = Modifier
          .padding(top = mediumPadding)
          // new code here:
          .semantics { 
              contentDescription = "Forgot your password? link"
          }
  )

这个按钮通过TalkBack实际上是可点击的吗?我认为用户仍然需要退出TalkBack模式才能使用该按钮。 - Mike Simpson

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