ComposeView 抢走了 AndroidTV 内容的焦点

问题描述 投票:0回答:1

我正在尝试在现有的 AndroidTV 应用程序中使用 Jetpack Compose。 我需要制作一个带有麦克风图标的按钮,如果它聚焦,它的颜色就会改变。像这样^

注意力不集中

专注

这是我的 ComposeView

<androidx.compose.ui.platform.ComposeView
    android:id="@+id/micBtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

这是我片段中的代码

binding.micBtn.setContent {
    var buttonResId by remember { mutableStateOf(R.drawable.speech_recognition_button_unfocused) }
    IconButton(
        modifier = Modifier
            .size(60.dp)
            .onFocusChanged {
                buttonResId = if (it.isFocused) {
                    R.drawable.speech_recognition_button_focused
                } else {
                    R.drawable.speech_recognition_button_unfocused
                }
            },
        onClick = onClick,
    ) {
        Icon(
            painter = painterResource(id = buttonResId),
            contentDescription = null,
            tint = Color.Unspecified,
        )
    }
}

看起来不错吧? 问题是,当我尝试关注此按钮时,焦点首先转到

AndroidComposeView
项目(根据我的
GlobalFocusListener
)。 只有我的第二个操作(单击、方向键导航)才能使我的内容集中。

所以,出于某种原因,内部

AndroidComposeView
从我的
Content

中窃取了焦点

有什么办法可以防止这种行为吗?我只需要关注我的内容,而不是

AndroidComposeView
包装。

android android-jetpack-compose android-tv
1个回答
0
投票

这是一个已知问题:

您可以创建一个扩展功能,可以将您的焦点转移给孩子。

@OptIn(ExperimentalFoundationApi::class)
fun ComposeView.setFocusableContent(content: @Composable () -> Unit) {
    isFocusable = true
    isFocusableInTouchMode = true
    val focusRequester = FocusRequester()

    onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
        if (hasFocus) focusRequester.requestFocus()
    }

    setContent {
        Box(modifier = Modifier.focusRequester(focusRequester).focusGroup()) {
            content.invoke()
        }
    }
}

用法非常简单。您现在可以使用

setContent
,而不是使用
setFocusableContent

binding.micBtn.setFocusableContent {
  // ...
}

与问题无关

要对组件中的焦点变化做出反应,您可以使用 androidx.tv.material3 库中的

IconButton
。默认情况下,当按钮聚焦时它会改变颜色,并且可以使用
colors
参数轻松更改不同状态(聚焦、按下等)的颜色。

用途:

androidx.tv.material3.IconButton(onClick = { }) {
    Icon(
        Icons.Filled.Mic, 
        contentDescription = "Mic"
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.