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

Jetpack Compose实现Surface项点击切换背景色(单选)

实现Column布局下的单选列表背景切换

核心思路

  • 在列表组件中维护选中项的状态,用remember保存选中设备的唯一标识(比如设备地址)
  • 给可点击容器添加选中状态参数,根据状态切换背景色
  • 点击项时更新选中状态,实现同一时间仅选一项的单选逻辑

修改后的完整代码

1. 调整ScanDeviceList,添加选中状态管理

@Composable
fun ColumnScope.ScanDeviceList(
    scanDeviceList: List<ScanResult>,
    modifier: Modifier = Modifier,
    pairSelectedDevice: () -> Unit
) {
    // 用设备地址作为唯一标识,初始为null表示无选中项
    val selectedDeviceAddress = remember { mutableStateOf<String?>(null) }

    Spacer(modifier = Modifier.height(16.dp))
    AnimatedVisibility(visible = scanDeviceList.isNotEmpty()) {
        Column(modifier = modifier) {
            Text(text = "扫描到的设备")
            Spacer(modifier = Modifier.height(8.dp))
            
            scanDeviceList.forEachIndexed { index, scanResult ->
                val isSelected = selectedDeviceAddress.value == scanResult.device.address
                ClickableItemContainer(
                    rippleColor = AquaLightOpacity10,
                    isSelected = isSelected,
                    content = {
                        ScanDeviceItem(index, scanResult, scanDeviceList.size)
                    }
                ) {
                    // 点击时切换选中状态:已选中则取消,未选中则设置为当前项
                    selectedDeviceAddress.value = if (isSelected) null else scanResult.device.address
                }
            }
            
            AvailableWarningText()
            PairSelectedDevice(pairSelectedDevice)
        }
    }
}

2. 修改ClickableItemContainer,支持选中背景色

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ClickableItemContainer(
    rippleColor: Color = TealLight,
    isSelected: Boolean = false,
    content: @Composable (MutableInteractionSource) -> Unit,
    clickAction: () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }
    // 根据选中状态切换背景色:选中用高亮色,未选中用白色
    val backgroundColor = if (isSelected) AquaLightOpacity10 else White

    CompositionLocalProvider(
        LocalRippleTheme provides AbcRippleTheme(rippleColor),
        content = {
            Surface(
                onClick = clickAction,
                interactionSource = interactionSource,
                color = backgroundColor,
                modifier = Modifier.fillMaxWidth()
            ) {
                content(interactionSource)
            }
        }
    )
}

3. 优化ScanDeviceItem(移除多余参数)

@Composable
fun ScanDeviceItem(
    index: Int,
    scanResult: ScanResult,
    totalCount: Int
) {
    Column {
        if (index == 0) {
            Divider(color = Cloudy, thickness = 1.dp)
        }
        Text(
            text = scanResult.device.name,
            modifier = Modifier.padding(vertical = 10.dp, horizontal = 16.dp)
        )
        // 最后一项不显示分割线
        if (index < totalCount - 1) {
            Divider(color = Cloudy, thickness = 1.dp)
        }
    }
}

关键说明

  • 用设备唯一标识维护选中状态,避免列表重排导致的状态混乱
  • Surface的color参数直接绑定选中状态,实现背景色实时切换
  • 支持取消选中:点击已选中项会清空选中状态,符合默认无选中项的需求
  • 补全原代码中缺失的Modifier参数,确保代码可运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:46:08