【问题标题】:Jetpack Compose Material3 - Label for SwitchJetpack Compose Material3 - 开关标签
【发布时间】:2022-11-06 20:02:11
【问题描述】:

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

到目前为止我的解决方案(它基本上只是扩展了现有的开关组件并添加了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
        )
    }
}

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

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

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

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

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

但这并不是最优的,因为它显示了对整个项目的连锁反应。

有没有更好的解决方案?甚至可能没有自定义组件?

【问题讨论】:

    标签: android android-jetpack-compose android-jetpack-compose-material3 material3


    【解决方案1】:

    你可以这样做。如果您不想在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)
                }
            )
        }
    }
    

    【讨论】:

    • 谢谢!这使它完全按预期工作。
    猜你喜欢
    • 2021-12-15
    • 2022-10-05
    • 2022-11-25
    • 2023-02-12
    • 2022-10-21
    • 2022-08-17
    • 2023-01-22
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多