melikaafrakhteh
melikaafrakhteh

Reputation: 367

How draw a line between 2 circles with canvas in jetpack compose?

I want draw a line between circles in the screen, I have start offset but I can not find end Offset? How can I find that? thank you

I add a hard code number (59.dp.toPx()) but I want to find left offset of next circle

this is hard code but I do not want hardcode float

my code:

  @Composable
fun StepProgressComponent(
    modifier: Modifier = Modifier,
    circleColor: Color,
    backGroundColor: Color,
    lineWidth: Float?,
    content: @Composable () -> Unit
){
    val radius = 16.dp
    Box(
        modifier = modifier,
        contentAlignment = Alignment.Center
    ){
        Canvas(modifier = Modifier) {
            drawCircleLine(
                color = circleColor,
                backGroundColor = backGroundColor,
                radius = radius,
                circleCenter = Offset(center.x, center.y),
                lineWidth = lineWidth
            )
        }
        content()
    }
}
private fun DrawScope.drawCircleLine(
    color: Color,
    backGroundColor: Color,
    radius: Dp,
    circleCenter: Offset,
    lineWidth: Float?,
) {
    val strokeWidth = 2.dp.toPx()

    drawCircle(
        color = backGroundColor,
        radius = radius.toPx(),
        alpha = 0.1f,
        center = circleCenter
    )
    drawCircle(
        color = color,
        radius = radius.toPx(),
        style = Stroke(width = strokeWidth),
        center = circleCenter
    )
    if (lineWidth != null)
        drawLine(
            color = color,
            start = Offset(circleCenter.x - 16.dp.toPx(), circleCenter.y),
            end = Offset((circleCenter.x - 16.dp.toPx()) - lineWidth, circleCenter.y),
            strokeWidth = strokeWidth
        )
}

Upvotes: 1

Views: 1217

Answers (2)

beigirad
beigirad

Reputation: 5724

You can take advantage of Row like this:

preview

private fun Progress() {
    val stepCount = 4

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        repeat(stepCount) { index ->
            Circle(modifier = Modifier.size(30.dp)) {
                if (index < 2) {
                    Icon(imageVector = Icons.Default.Check, contentDescription = null)
                }
            }
            if (index < stepCount - 1)
                Line(modifier = Modifier.weight(1f))
        }
    }
}

@Composable
private fun Circle(
    modifier: Modifier,
    content: @Composable (BoxScope.() -> Unit) = { }
) {
    Box(
        modifier = modifier.drawBehind {
            drawCircle(color = Color.Red, style = Stroke(2.dp.toPx()))
        },
        contentAlignment = Alignment.Center,
        content = content
    )
}

@Composable
private fun Line(modifier: Modifier) {
    Canvas(modifier = modifier) {
        drawLine(
            color = Color.Black,
            start = Offset.Zero,
            end = Offset(size.width, 0f),
            strokeWidth = 1.dp.toPx()
        )
    }
}

Upvotes: 4

Gabriele Mariotti
Gabriele Mariotti

Reputation: 363775

The start point of the line is:

x = circleCenter.x + radius + strokeWidth/2
y = circleCenter.y

The end point is:

x= startPointX + lineWidth
y= circleCenter.y

Something like:

if (lineWidth != null){
    val startLineX = circleCenter.x + radius.toPx() + strokeWidth/2
    drawLine(
        color = color,
        start = Offset(startLineX, circleCenter.y),
        end = Offset(startLineX + lineWidth, circleCenter.y),
        strokeWidth = strokeWidth
    )
}

enter image description here

The second circle have this center:

x = centerFirstCirle.x + (radius.toPx()*2) + lineWidth + (strokeWidth/2 *2)

enter image description here

Upvotes: 0

Related Questions