Jetpack Compose 中的 MaterialButtonToggleGroup

问题描述 投票:0回答:2

我想在 Jetpack Compose 中实现 MaterialButtonToggleGroup。该组件看起来像这样(图片取自here):

到目前为止,我得到了以下结果:

请注意,垂直蓝色边框旁边存在垂直灰色边框。在原作中,要么同时出现彩色边框,要么同时出现灰色。为了看得更清楚,请看一下这张带有超厚边框的图像:

如何实现两个按钮之间不存在垂直边框?我当前的代码如下所示:

    val cornerRadius = 8.dp

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp)
    ) {
        Spacer(modifier = Modifier.weight(1f))

        items.forEachIndexed { index, item ->
            OutlinedButton(
                onClick = { indexChanged(index) },
                shape = when (index) {
                    // left outer button
                    0 -> RoundedCornerShape(topStart = cornerRadius, topEnd = 0.dp, bottomStart = cornerRadius, bottomEnd = 0.dp)
                    // right outer button
                    items.size - 1 -> RoundedCornerShape(topStart = 0.dp, topEnd = cornerRadius, bottomStart = 0.dp, bottomEnd = cornerRadius)
                    // middle button
                    else -> RoundedCornerShape(topStart = 0.dp, topEnd = 0.dp, bottomStart = 0.dp, bottomEnd = 0.dp)
                },
                border = BorderStroke(1.dp, if(selectedIndex == index) { MaterialTheme.colors.primary } else { Color.DarkGray.copy(alpha = 0.75f)}),
                colors = if(selectedIndex == index) {
                    // selected colors
                    ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.primary.copy(alpha = 0.1f), contentColor = MaterialTheme.colors.primary)
                } else {
                    // not selected colors
                    ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.surface, contentColor = MaterialTheme.colors.primary)
                },
            ) {
                Text(
                    text = "Some text",
                    color = if(selectedIndex == index) { MaterialTheme.colors.primary } else { Color.DarkGray.copy(alpha = 0.9f) },
                    modifier = Modifier.padding(horizontal = 8.dp)
                )
            }
        }

        Spacer(modifier = Modifier.weight(1f))
    }
android kotlin android-button android-jetpack-compose modifier
2个回答
10
投票

MaterialButtonToggleGroup
中,为了防止双宽笔画,除了第一个将相邻笔画直接在彼此之上绘制的子项之外,所有笔画都有负 marginStart。

使用相同的解决方案:

OutlinedButton(
    modifier = when (index) {
        0 ->
            Modifier
                .offset(0.dp, 0.dp)
                .zIndex(if (selectedIndex == index) 1f else 0f)
        else ->
            Modifier
                .offset((-1 * index).dp, 0.dp)
                .zIndex(if (selectedIndex == index) 1f else 0f)
    },
    // Your code here


0
投票

结合之前的答案和OP代码,这是完整的代码(使用material3):

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex

@Composable
fun MaterialButtonToggleGroup(
    items: List<String>,
    onClick: (index: Int) -> Unit = {}
) {
    val cornerRadius = 8.dp

    val (selectedIndex, onIndexSelected) = remember { mutableStateOf<Int?>(null) }
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp)
    ) {
        Spacer(modifier = Modifier.weight(1f))

        items.forEachIndexed { index, item ->
            OutlinedButton(
                modifier = when (index) {
                    0 ->
                        Modifier
                            .offset(0.dp, 0.dp)
                            .zIndex(if (selectedIndex == index) 1f else 0f)

                    else ->
                        Modifier
                            .offset((-1 * index).dp, 0.dp)
                            .zIndex(if (selectedIndex == index) 1f else 0f)
                },
                onClick = {
                    onIndexSelected(index)
                    onClick(index)
                },
                shape = when (index) {
                    // left outer button
                    0 -> RoundedCornerShape(
                        topStart = cornerRadius,
                        topEnd = 0.dp,
                        bottomStart = cornerRadius,
                        bottomEnd = 0.dp
                    )
                    // right outer button
                    items.size - 1 -> RoundedCornerShape(
                        topStart = 0.dp,
                        topEnd = cornerRadius,
                        bottomStart = 0.dp,
                        bottomEnd = cornerRadius
                    )
                    // middle button
                    else -> RoundedCornerShape(topStart = 0.dp, topEnd = 0.dp, bottomStart = 0.dp, bottomEnd = 0.dp)
                },
                border = BorderStroke(
                    1.dp, if (selectedIndex == index) {
                        MaterialTheme.colorScheme.primary
                    } else {
                        Color.DarkGray.copy(alpha = 0.75f)
                    }
                ),
                colors = if (selectedIndex == index) {
                    // selected colors
                    ButtonDefaults.outlinedButtonColors(
                        containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f),
                        contentColor = MaterialTheme.colorScheme.primary
                    )
                } else {
                    // not selected colors
                    ButtonDefaults.outlinedButtonColors(
                        containerColor = MaterialTheme.colorScheme.surface,
                        contentColor = MaterialTheme.colorScheme.primary
                    )
                },
            ) {
                Text(
                    text = item,
                    color = if (selectedIndex == index) {
                        MaterialTheme.colorScheme.primary
                    } else {
                        Color.DarkGray.copy(alpha = 0.9f)
                    },
                    modifier = Modifier.padding(horizontal = 8.dp)
                )
            }
        }

        Spacer(modifier = Modifier.weight(1f))
    }
© www.soinside.com 2019 - 2024. All rights reserved.