简体   繁体   English

Jetpack Compose Material3 - Label for Switch

[英]Jetpack Compose Material3 - Label for Switch

I need to implement a switch with a label with Jetpack Compose and Material3.我需要使用带有 Jetpack Compose 和 Material3 的 label 实现一个开关。

My solution so far (it basically just extends the existing switch component and adds the label property):到目前为止我的解决方案(它基本上只是扩展了现有的开关组件并添加了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
        )
    }
}

This correctly displays the label (eg {Text("Test")} ) next to the switch.这会在开关旁边正确显示 label(例如{Text("Test")} )。

However, I would like to forward all click events on the label to the switch, so that you can touch the label to toggle the switch value.但是,我想将label上的所有点击事件转发到开关,以便您可以触摸label来切换开关值。

It basically should work like the old <Switch> component in XML layouts.它基本上应该像 XML 布局中的旧<Switch>组件一样工作。

One idea I had was adding a modifier to the container like so:我的一个想法是向容器添加一个修饰符,如下所示:

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

But this is not optimal as it shows a ripple effect on the whole item.但这并不是最优的,因为它显示了对整个项目的连锁反应。

Is there any better solution?有没有更好的解决方案? Maybe even without a custom component?甚至可能没有自定义组件?

You can do it like this.你可以这样做。 If you don't want ripple on Switch set onCheckedChange = null如果您不想在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)
            }
        )
    }
}

You can use the wrapContentSize modifier in your Row to avoid the ripple in the whole width.您可以在Row中使用wrapContentSize修饰符来避免整个宽度的波纹。

var isChecked by remember { mutableStateOf(false) }

Row(
    modifier = Modifier
        .wrapContentSize()
        .toggleable(
            value = isChecked,
            onValueChange = { isChecked = it },
        ),
) {
    Text(text = "Hello")
    Switch(
       checked = isChecked, 
       onCheckedChange = null,
       modifier = Modifier.semantics { contentDescription = "Hello" }
    )
}

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM