如何在 LazyRow 中为每个项目获取 onFocusChanged?

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

我正在致力于辅助功能实现(盲人残疾),一旦用户向左或向右滑动以将焦点移到 LazyRow 中的项目上,我需要知道列表中当前处于辅助功能焦点中的项目索引。

我有这样一个暗示:

    LazyRow(
        state = listState,
        modifier = modifier,
        flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
    ) {
        itemsIndexed(items = episodes, key = { index, _ ->
            "$CARD_KEY$index"
        }) { index, item ->
            item.apply {

            CustomCard(
                episode = item.episode,
                modifier = Modifier
                    .wrapContentWidth()
                    .background(
                        BrandedTheme._ui_core__bottomsheet__backgroundColor
                    )
                    .onFocusChanged {
                        if (it.isFocused) {
                            if (listState.isScrollInProgress.not() && selectedEpisodeIndex != -1) {
                                GlobalScope.launch {
                                    listState.scrollToItem(index = index)
                                }
                            }
                        }
                    }
                    .wrapContentHeight()
                    .semantics(mergeDescendants = true) {
                        isTraversalGroup = true
                        traversalIndex = -1f
                    },
                index = index
            )
        }
    }
}

因此,列表中的每个项目都有一个具有属性 -

onFocusChanged
的修饰符,问题是该事件仅在列表初始化时触发,但是当用户移动辅助功能焦点(通过向左/向右滑动)时,我看到(在屏幕上)下一个项目获得焦点,但在代码中
onFocusChanged
未触发。

我在这里缺少什么?

UPD

添加了

onFocusEvent()
focusTarget()
,现在好像我收到了更改元素的事件,但有2个问题:

  1. 所有元素都具有状态
    Inactive
    (无活动状态)。
  2. 索引不显示当前屏幕上元素的索引。
    LazyRow(
        state = listState,
        modifier = modifier,
        flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
    ) {
        itemsIndexed(items = episodes, key = { index, _ ->
            "$CARD_KEY$index"
        }) { index, item ->
            item.apply {

            CustomCard(
                episode = item.episode,
                modifier = Modifier
                    .wrapContentWidth()
                    .onFocusEvent {
                        Log.e("HERE", "111 onFocusEvent: $index :: $it")
                    }        
                    .background(
                        BrandedTheme._ui_core__bottomsheet__backgroundColor
                    )
                    .onFocusChanged {
                        if (it.isFocused) {
                            if (listState.isScrollInProgress.not() && selectedEpisodeIndex != -1) {
                                GlobalScope.launch {
                                    listState.scrollToItem(index = index)
                                }
                            }
                        }
                    }
                    .focusTarget()
                    .wrapContentHeight()
                    .semantics(mergeDescendants = true) {
                        isTraversalGroup = true
                        traversalIndex = -1f
                    },
                index = index
            )
        }
    }
}

我的另一个想法是创建一个自定义

rememberSnapFlingBehavior
,因为我注意到在辅助功能模式下,屏幕上的焦点会切换并拉动下一个元素,但它不会将其置于屏幕中心(尽管这在没有辅助功能的情况下也可以工作)模式)。但最终这个想法也没能实现。

kotlin android-jetpack-compose accessibility android-jetpack
1个回答
0
投票

如果我没记错的话,Compose 默认情况下不会将焦点更改传播到父可组合项(以提高性能)。在您的情况下,您可能需要通过从父可组合项传递回调函数来手动传播焦点更改。

此外,当 traversalIndex 设置为 -1f 时,我认为该项目不包含在可访问性焦点遍历中,这也可能是您问题的一部分。作为黑暗中的一击,你尝试过设置

traversalIndex = index.toFloat()
吗?

© www.soinside.com 2019 - 2024. All rights reserved.