我正在尝试创建一个模拟面包屑的可组合项。像这样的东西。 当前步骤将具有粉红色的双圆圈,已访问的步骤将具有正常的粉红色点,而未访问的步骤将具有灰色点。线路逻辑如下图所示。
我一直在尝试 Canvas,但从来没有成功过。而且我也无法以“公司”为中心......
这是我的代码。我认为我做得太过了,所以请建议如何使用 Canvas 进行重构。我确信可以用更少的代码来完成。
@Composable
fun PlatfoBreadCrumb(
modifier: Modifier = Modifier,
currentStep: Int,
) {
Column(
modifier = modifier
.fillMaxWidth(),
) {
Row(
modifier = modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
ProgressStep(
text = "About You",
isSelected = currentStep == 1
)
ProgressStep(
text = "Company",
isSelected = currentStep == 2
)
ProgressStep(
text= "Activity",
isSelected = currentStep == 3
)
}
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.CenterStart
) {
Row(
modifier = modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
repeat(3) { index ->
if (index < currentStep - 1) {
Line(
modifier = Modifier.weight(1f),
color = colorResource(id = R.color.primary_50)
)
}
ProgressDots(isSelected = currentStep == index)
}
}
}
}
}
@Composable
fun Line(
modifier: Modifier = Modifier,
color: Color
) {
Canvas(
modifier = modifier
) {
drawLine(
color = color,
start = Offset.Zero,
end = Offset(size.width, 0f),
strokeWidth = 1.dp.toPx()
)
}
}
@Composable
fun ProgressStep(
text: String,
isSelected: Boolean
) {
Text(
text = text,
color = if(isSelected) colorResource(id = R.color.primary_50) else
colorResource(id = R.color.neutral_50),
)
}
@Composable
fun ProgressDots(
isSelected: Boolean
) {
if (isSelected) {
Box(
modifier = Modifier
.size(20.dp)
.border(
1.dp,
color = colorResource(id = R.color.primary_50),
shape = CircleShape,
), contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(16.dp)
.background(
color = colorResource(id = R.color.primary_50), shape = CircleShape
)
)
}
} else {
Box(
modifier = Modifier
.size(20.dp)
.border(
0.dp,
color = Color.Transparent,
shape = CircleShape,
), contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(16.dp)
.background(
color = colorResource(id = R.color.neutral_50), shape = CircleShape
)
)
}
}
}
@Preview(showBackground = true)
@Composable
fun BreadCrumbPreview() {
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(48.dp),
color = Color.Transparent
) {
PlatfoBreadCrumb(
currentStep = 1
)
}
}
感谢您的关注!
我一直在努力并提出了一种解决方案,在我看来这不是最好的解决方案,但是它有效。
@Composable
fun PlatfoBreadCrumb(
modifier: Modifier = Modifier,
selectedStep: Int,
) {
Column(
modifier = modifier
.fillMaxWidth(),
) {
Row(
modifier = modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
repeat(3) {
val text = when(it) {
0 -> "About You"
1 -> "Company"
2 -> "Activity"
else -> ""
}
ProgressStep(
text = text,
step = it,
selectedStep = selectedStep
)
}
}
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.CenterStart
) {
ProgressLine(
modifier.fillMaxWidth(),
step = selectedStep
)
Row(
modifier = modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
repeat(3) {
ProgressDots(
step = it,
selectedStep = selectedStep
)
}
}
}
}
}
@Composable
fun ProgressStep(
text: String,
step: Int,
selectedStep: Int,
) {
val textColor = when(selectedStep) {
0 -> {
if(step == 0) colorResource(id = R.color.neutral_95) else
colorResource(id = R.color.neutral_50)
}
1 -> {
if(step <= 1) colorResource(id = R.color.neutral_95) else
colorResource(id = R.color.neutral_50)
}
2 -> colorResource(id = R.color.neutral_95)
else -> colorResource(id = R.color.neutral_50)
}
val fontWeight = if (selectedStep == step) {
FontWeight.Bold
} else {
FontWeight.Normal
}
Text(
text = text,
color = textColor,
fontWeight = fontWeight
)
}
@Composable
fun ProgressDots(
step: Int,
selectedStep: Int,
) {
val color = when(selectedStep) {
0 -> {
if(step == 0) colorResource(id = R.color.primary_50) else
colorResource(id = R.color.neutral_50)
}
1 -> {
if(step <= 1) colorResource(id = R.color.primary_50) else
colorResource(id = R.color.neutral_50)
}
2 -> colorResource(id = R.color.primary_50)
else -> colorResource(id = R.color.neutral_50)
}
if (selectedStep == step) {
Box(
modifier = Modifier
.size(20.dp)
.border(
1.dp,
color = color,
shape = CircleShape,
), contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(16.dp)
.background(
color = color, shape = CircleShape
)
)
}
} else {
Box(
modifier = Modifier
.size(20.dp)
.border(
0.dp,
color = Color.Transparent,
shape = CircleShape,
), contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(16.dp)
.background(
color = color, shape = CircleShape
)
)
}
}
}
@Composable
private fun ProgressLine(
modifier: Modifier,
step: Int
) {
val remain = colorResource(id = R.color.neutral_50)
val visited = colorResource(id = R.color.primary_50)
Canvas(
modifier = modifier
) {
when(step) {
0 -> {
drawLine(
color = remain,
start = Offset(20.dp.toPx(), 0f),
end = Offset(size.width - 10, 0f),
strokeWidth = 1.dp.toPx())
}
1 -> {
drawLine(
color = visited,
start = Offset(16.dp.toPx(), 0f),
end = Offset(size.width/2 - 10.dp.toPx(), 0f),
strokeWidth = 1.dp.toPx())
drawLine(
color = remain,
start =Offset(size.width/2 + 10.dp.toPx(), 0f),
end = Offset(size.width - 10, 0f),
strokeWidth = 1.dp.toPx())
}
2 -> {
drawLine(
color = visited,
start = Offset(16.dp.toPx(), 0f),
end = Offset(size.width - 20.dp.toPx(), 0f),
strokeWidth = 1.dp.toPx())
}
}
}
}
@Preview(showBackground = true)
@Composable
fun BreadCrumbPreview() {
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(48.dp),
color = Color.Transparent
) {
PlatfoBreadCrumb(
selectedStep = 1
)
}
}
随时提供重构和优化此解决方案。 谢谢!!