我正在构建一个场景,点击一个按钮会生成一个新的屏幕标题和内容。根据可访问性要求,点击一个按钮会将TalkBack焦点放在屏幕标题上,这样用户就可以听到新内容的内容。
屏幕应该是这样的:
Column(){
Title()
Content()
RefreshContentButton()
}
我使用了一个FocusRequester
示例来请求按钮被点击时的焦点,这是第一次**很好地工作,当用户返回到刷新按钮并点击它时,焦点不会改变。
我已经设置了一个显示该问题的示例。在启用TalkBack的情况下,第一次单击按钮成功地将焦点放在相应的Focusable
上,第二次单击没有任何操作。但是,如果交替单击按钮,则一切正常。
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalComposeUiApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val (ref1, ref2) = remember { FocusRequester.createRefs() }
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceBetween,
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
Focusable("Focusable #1", ref1)
Focusable("Focusable #2", ref2)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
Button(
onClick = {
ref1.requestFocus()
}) {
Text(text = "Focus on #1")
}
Button(
onClick = {
ref2.requestFocus()
}) {
Text(text = "Focus on #2")
}
}
}
}
}
}
@Composable
fun Focusable(text: String, focusRequester: FocusRequester) {
Box(
modifier = Modifier.height(100.dp),
contentAlignment = Alignment.Center,
) {
Text(text = text, modifier = Modifier
.focusRequester(focusRequester)
.focusable(true)
.focusProperties {
canFocus = true
}
.focusTarget())
}
}
1条答案
按热度按时间deyfvvtc1#
我现在遇到了完全相同的问题,通过调试androix.compose.ui.focus代码,我可以看到原因。在FocusRequester.kt中存在requestFocus函数。它调用FocusTransactions.kt中的一个内部函数requestFocus。在这里有一个when语句,当我们请求焦点的特定节点是Active、Captured、Deactivated或DeactivedParent时,焦点状态不会发生变化。
问题似乎是,当您请求关注某个节点时,该节点第一次将其初始状态从Inactive变为Active。它仍处于Active状态,因此,如果您请求关注同一个节点,它不会执行任何操作。似乎请求关注另一个节点(如示例代码中所示)会将此状态设置回Inactive。这就是为什么您可以在两个示例节点之间交替焦点,但不能在同一节点上重复焦点请求。
我一直未能找到解决办法(甚至是一个很蹩脚的)。我试着用FocusManager调用clearFocus。也试着用FocusRequester的freeFocus函数,但这只是将捕获状态更改为活动。我认为我们需要在FocusRequester中添加一个新的公共函数,该函数调用FocusTransactions.kt中的clearFocus,因为它将活动状态设置为非活动。这将允许我们在调用requestFocus之前确保状态是正确的。更好的是,我觉得当我们使用talkback遍历时,它应该自动将焦点状态从Active设置为Inactive。
最新的ComposeUI发布说明提到焦点系统是使用新的实验性Modifier.Node API重写的。然而,据我所知,这并没有改变实际的行为。只是焦点系统内部的工作方式。我用最新的alpha版本尝试了你的示例代码,问题仍然存在。