我想在 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))
}
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
结合之前的答案和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))
}