You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为FlowRow的RadioButton配置无障碍语义:如何正确设置CollectionInfo?

解决FlowRow中RadioButton无障碍集合信息配置问题

不需要自定义FlowRow,通过Compose的语义API结合状态就能实现需求,以下是具体方案:

核心思路

无障碍读屏对集合信息的核心需求是总项数和当前项的位置,FlowRow的动态行列数并非必需——多数场景下,读屏只需告知用户“共X项,当前是第Y项”即可。若确实需要精确行列信息,也可通过布局监听实现,无需自定义组件。

基础实现(满足“共X项”需求)

直接利用总项数配置CollectionInfo和CollectionItemInfo,无需计算动态行列:

val totalItems = 5
val selected by remember { mutableStateOf(0) }

FlowRow(
    modifier = Modifier
        .selectableGroup()
        .semantics {
            // 配置集合总信息:总项数5,布局类型设为网格(对应FlowRow的流式布局)
            collectionInfo = CollectionInfo(
                size = totalItems,
                layoutType = CollectionLayoutType.Grid
            )
        }
) {
    repeat(totalItems) { index ->
        RadioButton(
            selected = selected == index,
            onClick = { selected = index },
            modifier = Modifier.semantics {
                // 配置当前项的集合位置信息:索引、总项数
                collectionItemInfo = CollectionItemInfo(
                    index = index,
                    size = totalItems
                )
            }
        )
    }
}

此时读屏会播报类似“共5项的网格,第1项”“已选中,共5项的网格,第3项”的内容,满足基础需求。

进阶实现(获取动态行列数)

若需要读屏播报行列位置(如“第2行第1列,共2行3列”),可通过onGloballyPositioned监听布局尺寸计算行列:

val totalItems = 5
val selected by remember { mutableStateOf(0) }
val flowRowWidth = remember { mutableStateOf(0) }
val itemWidth = remember { mutableStateOf(0) }
val columnCount by remember { derivedStateOf { 
    if (flowRowWidth.value > 0 && itemWidth.value > 0) {
        (flowRowWidth.value / itemWidth.value).coerceAtLeast(1)
    } else 1
} }
val rowCount by remember { derivedStateOf { 
    (totalItems + columnCount - 1) / columnCount // 向上取整计算行数
} }

FlowRow(
    modifier = Modifier
        .selectableGroup()
        .onGloballyPositioned { coordinates ->
            flowRowWidth.value = coordinates.size.width
        }
        .semantics {
            collectionInfo = CollectionInfo(
                size = totalItems,
                layoutType = CollectionLayoutType.Grid,
                rowCount = rowCount,
                columnCount = columnCount
            )
        }
) {
    repeat(totalItems) { index ->
        RadioButton(
            selected = selected == index,
            onClick = { selected = index },
            modifier = Modifier
                .onGloballyPositioned { coordinates ->
                    // 仅保存第一个item的宽度(假设所有item尺寸一致)
                    if (index == 0) {
                        itemWidth.value = coordinates.size.width
                    }
                }
                .semantics {
                    collectionItemInfo = CollectionItemInfo(
                        index = index,
                        size = totalItems,
                        rowIndex = index / columnCount,
                        columnIndex = index % columnCount
                    )
                }
        )
    }
}

说明:

  • 通过onGloballyPositioned获取FlowRow总宽度和单个RadioButton的宽度,计算每行可容纳的列数
  • 用derivedStateOf实时计算行列数,确保布局变化时自动更新
  • 每个item的行列索引通过index / columnCount和index % columnCount计算

内容的提问来源于stack exchange,提问作者coding4mobile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:09:56