撰写看起来相似的进度指示器面包屑

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

我正在尝试创建一个模拟面包屑的可组合项。像这样的东西。 当前步骤将具有粉红色的双圆圈,已访问的步骤将具有正常的粉红色点,而未访问的步骤将具有灰色点。线路逻辑如下图所示。

我一直在尝试 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
        )
    }
}

感谢您的关注!

android android-jetpack-compose android-canvas android-jetpack-compose-canvas
1个回答
0
投票

我一直在努力并提出了一种解决方案,在我看来这不是最好的解决方案,但是它有效。


@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
        )
    }
}

随时提供重构和优化此解决方案。 谢谢!!

© www.soinside.com 2019 - 2024. All rights reserved.