Home > Back-end >  How to make this triangle indicator to rotate and move in android jetpack compose?
How to make this triangle indicator to rotate and move in android jetpack compose?

Time:01-09

Timer Image Reference

I have highlighted (red) my problem in the image; I want to animate that blue indicator triangle.

The triangle is moving, but it is not properly moving. I don't know what I am missing.

Timer Image with what I have achieved so far: Timer Image with what I have achieved so far

This is my code so far.

        val center = Offset(size.width / 2f, size.height / 2f)
        val beta = (250f * value   145f) * (PI / 180f).toFloat()
        val r = size.width / 2f
        val a = cos(beta) * r
        val b = sin(beta) * r
        drawPoints(
            listOf(Offset(center.x   a, center.y   b)),
            pointMode = PointMode.Points,
            color = Color.Gray,
            strokeWidth = (strokeWidth * 2.2f).toPx(),
            cap = StrokeCap.Round
        )
        drawPoints(
            listOf(Offset(center.x   a, center.y   b)),
            pointMode = PointMode.Points,
            color = Color.White,
            strokeWidth = (strokeWidth * 2f).toPx(),
            cap = StrokeCap.Round
        )
        drawPoints(
            listOf(Offset(center.x   a, center.y   b)),
            pointMode = PointMode.Points,
            color = PrimaryBlueColor,
            strokeWidth = (strokeWidth * 1f).toPx(),
            cap = StrokeCap.Round
        )



        drawImage(
            image = vector,
            topLeft = Offset(center.x   a, center.y   b)
        )

CodePudding user response:

Rotation in Compose is very simple. Insider Canvas or actually DrawScope call

rotate(value) {
  // Anything you draw here is rotate by angle in degrees
}

As

val centerX = center.x
val centerY = center.y
val triangleWidthPx = triangleWidth.toPx()
val triangleHeightPx = triangleHeight.toPx()
val diff = offsetX.toPx()
val strokeWidthPx = strokeWidth.toPx()

val triangleStartX = centerX   radiusPx - diff

if (trianglePath.isEmpty) {
    trianglePath.apply {
        moveTo(triangleStartX, centerY - triangleHeightPx / 2)
        lineTo(triangleStartX   triangleWidthPx, centerY)
        lineTo(triangleStartX, centerY    triangleHeightPx / 2)
        lineTo(triangleStartX, centerY - triangleHeightPx / 2)
    }
}


rotate(value) {
    drawPath(trianglePath, Color(0xff243f8d))
}

Full Sample

Demonstration

enter image description here

Code

@Composable
private fun CanvasRotationSample() {

    var value by remember {
        mutableStateOf(0f)
    }

    val diameter = 160.dp

    Spacer(modifier = Modifier.height(50.dp))
    Slider(value = value, onValueChange = { value = it }, valueRange = 0f..360f)
    Spacer(modifier = Modifier.height(50.dp))

    val trianglePath = remember {
        Path()
    }

    val triangleWidth = 24.dp
    val triangleHeight = 24.dp
    val offsetX = 2.dp
    Box(
        Modifier
            .fillMaxWidth()
            .aspectRatio(1f),
        contentAlignment = Alignment.Center
    ) {
        Canvas(
            modifier = Modifier.matchParentSize()
        ) {

            val radius = diameter.toPx() / 2
            val centerX = center.x
            val centerY = center.y
            val triangleWidthPx = triangleWidth.toPx()
            val triangleHeightPx = triangleHeight.toPx()
            val diff = offsetX.toPx()

            val triangleStartX = centerX   radius - diff

            if (trianglePath.isEmpty) {
                trianglePath.apply {
                    moveTo(triangleStartX, centerY - triangleHeightPx / 2)
                    lineTo(triangleStartX   triangleWidthPx, centerY)
                    lineTo(triangleStartX, centerY    triangleHeightPx / 2)
                    lineTo(triangleStartX, centerY - triangleHeightPx / 2)
                }
            }

            rotate(value) {
                drawPath(trianglePath, Color(0xff243f8d))
            }
        }

        Box(
            modifier = Modifier
                .shadow(4.dp, CircleShape)
                .background(Color(0xfff9f9fa))
                .size(diameter)
                .padding(24.dp)
        ) {
            Box(
                modifier = Modifier
                    .shadow(1.dp, CircleShape)
                    .background(Color.White)
                    .matchParentSize()
                    .drawBehind {
                        drawArc(
                            color = Color(0xff6175ad),
                            useCenter = true,
                            startAngle = -60f,
                            sweepAngle = 120f
                        )
                    }
            )
        }
    }
}
  • Related