Jetpack Compose Material3 - Switch 标签

Sap*_*ven 5 android android-jetpack-compose android-jetpack-compose-material3 material3

我需要使用 Jetpack Compose 和 Material3 实现带有标签的开关。

到目前为止我的解决方案(它基本上只是扩展现有的 switch 组件并添加属性label):

@Composable
fun LabeledSwitch(
    checked: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    modifier: Modifier = Modifier,
    thumbContent: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    colors: SwitchColors = SwitchDefaults.colors(),
    label: (@Composable () -> Unit),
) {
    Row(
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
    ) {
        label()
        Switch(
            checked = checked,
            onCheckedChange = onCheckedChange,
            thumbContent = thumbContent,
            enabled = enabled,
            interactionSource = interactionSource,
            colors = colors
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

{Text("Test")}这将正确显示开关旁边的标签(例如)。

但是,我想将标签上的所有点击事件转发到开关,以便您可以触摸标签来切换开关值。

它基本上应该像<Switch>XML 布局中的旧组件一样工作。

我的一个想法是向容器添加一个修饰符,如下所示:

Row(
    horizontalArrangement = Arrangement.SpaceBetween,
    verticalAlignment = Alignment.CenterVertically,
    modifier = modifier.then(Modifier
        .clickable { onCheckedChange?.invoke(!checked) }
    )
Run Code Online (Sandbox Code Playgroud)

但这并不是最佳选择,因为它会对整个项目产生连锁反应。

还有更好的解决办法吗?也许甚至没有自定义组件?

Thr*_*ian 6

你可以这样做。如果你不想在Switch片场出现涟漪onCheckedChange = null

在此输入图像描述

@Composable
private fun SwitchWithLabel(label: String, state: Boolean, onStateChange: (Boolean) -> Unit) {

    val interactionSource = remember { MutableInteractionSource() }
    Row(
        modifier = Modifier
            .clickable(
                interactionSource = interactionSource,
                // This is for removing ripple when Row is clicked
                indication = null,
                role = Role.Switch,
                onClick = {
                    onStateChange(!state)
                }
            )
            .padding(8.dp),
        verticalAlignment = Alignment.CenterVertically

    ) {

        Text(text = label)
        Spacer(modifier = Modifier.padding(start = 8.dp))
        Switch(
            checked = state,
            onCheckedChange = {
                onStateChange(it)
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)