Я пытаюсь создать собственный индикатор выполнения в Compose, где каждый шаг представлен точкой, а под каждой точкой есть текстовая метка. Однако у меня возникли проблемы с выравниванием текстовых меток так, чтобы они были правильно центрированы под каждой точкой.
Это то, чего я пытаюсь достичь:
Вот моя текущая реализация и как она выглядит:
data class Step(val title: String = "") {}
StepsProgressView(
steps = listOf(Step("text"),Step("something"),Step("some"),Step("DD"),Step("Ssss cccc")),
completedIndex = 2
)
@Composable
fun StepsProgressView(
steps: List<Step>,
modifier: Modifier = Modifier,
lineWidth: Dp = 1.dp,
completedIndex: Int = 2
) {
Column(modifier = modifier) {
Box(contentAlignment = Alignment.Center) {
Canvas(modifier = Modifier.fillMaxWidth()) {
val width = drawContext.size.width
val height = drawContext.size.height
val yOffset = height / 2
val itemWidth = width / steps.size
var startOffset = itemWidth / 2
var endOffset = startOffset
val barWidth = lineWidth.toPx()
repeat(steps.size - 1) { index ->
endOffset += itemWidth
drawLine(
brush = SolidColor(if (index < completedIndex) Color.Blue else Color.Gray),
start = Offset(startOffset, yOffset),
end = Offset(endOffset, yOffset),
strokeWidth = barWidth
)
startOffset = endOffset
}
}
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically,
) {
repeat(steps.size) { index ->
Box(contentAlignment = Alignment.Center) {
// last index image
if (index == steps.lastIndex)
Image(
painter = painterResource(id = androidx.biometric.R.drawable.fingerprint_dialog_fp_icon),
contentDescription = null,
modifier = Modifier.size(24.dp),
contentScale = ContentScale.Crop
)
// circles box
else
Box(
modifier = Modifier
.size(12.dp)
.drawBehind {
drawCircle(
color =
if (index <= completedIndex) Color.Blue
else Color.Gray
)
},
contentAlignment = Alignment.Center,
content = {})
}
}
}
}
Spacer(Modifier.height(8.dp))
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround
) {
steps.forEachIndexed { index, step ->
Text(
text = step.title,
style = TextStyle(
color =
if (steps.indexOf(step) <= completedIndex) Color.Blue
else Color.Gray,
fontSize = 13.sp,
textAlign = TextAlign.Center
),
modifier = Modifier
.wrapContentWidth()
.weight(1f)
)
}
}
}
}
Проблема, с которой я столкнулся, заключается в том, что текстовые метки под точками не идеально выровнены по центру. Я хочу, чтобы каждая текстовая метка располагалась по центру под соответствующей точкой.
Любые предложения будут высоко оценены. Спасибо!
«HelpText» — просто компонуемый пользовательский текст, исправлено. «drawContext» доступен из области Canvas. И вопрос, с которым я столкнулся, заключается в том, как сделать так, чтобы последние текстовые представления из индикатора выполнения отображались по центру под точками, потому что именно они смещены, отчасти потому, что последний индекс представляет собой изображение в два раза больше, чем другие точки. Утром отредактирую свой пост и выложу скриншот
Проблема вызвана тем, что последнее изображение в два раза больше остальных точек. Когда я выравниваю их до одинакового размера, тексты выравниваются идеально.
Проблема в том, что ваше последнее индексное изображение больше остальных кругов. Это нарушает расположение вашего ряда, которое зависит от weight(1f)
равномерного распределения пространства.
Один из способов решения этой проблемы — сделать последнее индексное изображение того же размера, что и другие круги, а затем, тем не менее, нарисовать изображение желаемого размера:
// last index image
if (index == steps.lastIndex)
Box(modifier = Modifier.size(12.dp)) {
Image(
painter = painterResource(id = R.drawable.barImage),
contentDescription = null,
modifier = Modifier.requiredSize(24.dp),
contentScale = ContentScale.Crop
)
}
// circles box
else
...
Возможно, вам придется добавить дополнительное дополнение к строке, чтобы изображение, превышающее ожидаемое, поместилось.
Огромное спасибо, у меня появилась возможность попробовать!
В настоящее время ваш код не совсем воспроизводим. Ваш
HelpText
Composable не включен, и мы не знаем, откуда взялсяdrawContext
. Ваш подход с использованием модификатораweight
выглядит нормально, тексты должны быть распределены равномерно. Я думаю, что реальный вопрос, с которым вы столкнулись, заключается в том, как сделать так, чтобы первая точка индикатора выполнения отображалась над центром первого текста. Или, наоборот, _как указать отступы слева от строки текста, чтобы первый текст располагался по центру под первой точкой индикатора выполнения. А не могли бы вы отредактировать свое сообщение и приложить скриншот?