我正在try 在我现有的androidtv应用程序中使用Jetpack Compose. 我需要做一个带有麦克风图标的按钮,如果对焦了,它会改变 colored颜色 .像这样^

无重点

enter image description here

聚焦

enter image description here

这是我的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.is聚焦) {
                    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). 只有我的第二个动作(点击,D-Pad导航)使我的内容变得集中.

所以,出于某种原因,内部AndroidComposeView从我的Content中偷走了注意力

有什么办法可以防止这种行为吗?我只需要专注于我的内容,而不是AndroidComposeView个包装器.

推荐答案

这是一个已知的问题,将焦点从ComposeView外部移动到ComposeView内部需要用户输入2次,而不是只需1:b/292432034

你可以创建一个扩展函数,只需用户输入一次,就可以将焦点转移到子元素身上.

@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()
        }
    }
}

用法非常简单.您现在可以使用setFocusableContent,而不是setContent.

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

与问题无关

要对组件中的焦点变化做出react ,您可以使用androidx.tv.material3库中的IconButton.默认情况下,它会在按钮被聚焦时更改 colored颜色 ,并且可以很容易地使用colors参数更改不同状态(聚焦、按下等)的 colored颜色 .

用途:

androidx.tv.material3.IconButton(onClick = { }) {
    Icon(
        Icons.Filled.Mic, 
        contentDescription = "Mic"
    )
}

Android相关问答推荐

房间数据库迁移未正确处理:原因:java.lang. IllegalState异常:

如何使用单个代码库使用不同的firebase项目创建多个应用程序ID apk

将Android Studio插件复制到离线网络

如何go 除回调流中不可用的状态?

fillMaxHeight中的分数在列内不起作用(android jetpack compose)

如何从sqlite数据库中检索数据到碎片android?

如何用帆布在喷气背包中画一个圆环?

更改选定的切换轨道 colored颜色

警告:应用必须面向 Android 13(API 级别 33)或更高版本.确实如此

列表更改时,RecyclerView 中的列表不会更新

在Android RoomDB中使用Kotlin Flow和删除数据时如何解决错误?

Jetpack Compose 中的滑动按钮菜单

react 从输入中找到路径'lib/arm64-v8a/libfbjni.so'的本机2个文件

无法解析依赖项'com.github.smarteist:autoimageslider:1.4.0-appcompat'

Android Compose 创建抖动动画

我的 react native 项目的发布签名 apk 没有在设备中打开,而且它创建的尺寸非常小

这是 let 函数的正确用法吗?

禁用通知权限后启动前台服务导致崩溃(Android 13)

多个项目 react-native android 构建错误

在 Android 10 (API 29) 中隐藏状态栏并在应用程序中使用其空间