Med Hadi Hassine
Med Hadi Hassine

Reputation: 64

Rotate Image with single finger Using Compose

I have been trying to rotate an image using a single finger without success. So i wanted to know if anyone of you have succeeded doing this. this is a part of my code.

DrawButton(
                        modifier = Modifier
                            .offset(0.dp, (height - 17.5).dp)
                            .pointerInput(Unit) {
                                detectDragGestures { change, _ ->
                                    boxCenter = Point(
                                        box.startX + box.width / 2,
                                        box.startY + box.height / 2
                                    )
                                    val anglePoint=getAnglePoint(boxCenter,
                                        Point(box.startX,box.startY+box.height),angle
                                    )
                                    val rawX = change.position.x +anglePoint.x
                                    val rawY = change.position.y + anglePoint.y

                                    lastX = change.previousPosition.x + anglePoint.x
                                    lastY = change.previousPosition.y + anglePoint.y
                                    if (lastX != -1f) {
//                                        if (abs(rawX - lastX) < 5 && abs(rawY - lastY) < 5) {
//                                            Log.e("detectDragGestures","detectDragGestures")
//
//                                            return@detectDragGestures
//                                        }
                                    }
                                    pushPoint = getPushPoint(box, change.previousPosition)

                                    val O: Point = boxCenter
                                    val A: Point = pushPoint
                                    val B = getPushPoint(box, change.position)
                                    val dOA = getDistance(O, A)
                                    val dOB = getDistance(O, B)
                                    val fz = (A.x - O.x) * (B.x - O.x) + (A.y - O.y) * (B.y - O.y)
                                    val fm = dOA * dOB
                                    var comAngle =
                                        180 * acos((fz / fm).toDouble()) / PI
                                    if (java.lang.Double.isNaN(comAngle)) {
                                        Log.e("isNaN", "isNaN")
                                        comAngle =
                                            if (lastComAngle < 90 || lastComAngle > 270) 0.toDouble() else 180.toDouble()
                                       // return@detectDragGestures
                                    } else if ((B.y - O.y) * (A.x - O.x) < (A.y - O.y) * (B.x - O.x)) {
                                        comAngle = 360 - comAngle
                                    }
                                    lastComAngle = comAngle.toFloat()
                                    val targetAngle: Float = (angle + comAngle).toFloat()
                                    Log.e("targetAngle","$targetAngle")
                                    Log.e("angle","$angle")
                                    angle = targetAngle % 360
                                }
                            },
                        R.drawable.ic_rotate
                    )

I have tried to convert this solution to compose without success: https://github.com/ryanch741/android-view-rotate-zoom-single-finger/tree/master/src/com/example/testimg. Thanks previously for your help

enter image description here

Upvotes: 4

Views: 748

Answers (1)

nglauber
nglauber

Reputation: 23954

I found a solution basically converting this answer to Compose.

@ExperimentalComposeUiApi
@Composable
fun OneFingerImageRotation() {
    var viewRotation = remember { 0.0 }
    var fingerRotation = remember { 0.0 }
    var rotation by remember {
        mutableStateOf(0.0)
    }
    val density = LocalDensity.current
    BoxWithConstraints {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Gray)
                .pointerInteropFilter { event ->
                    val x: Float = event.x
                    val y: Float = event.y
                    val xc: Float = with(density) { maxWidth.toPx() } / 2f
                    val yc: Float = with(density) { maxHeight.toPx() } / 2f

                    when (event.action) {
                        MotionEvent.ACTION_DOWN -> {
                            viewRotation = rotation
                            fingerRotation = Math.toDegrees(atan2((x - xc).toDouble(), (yc - y).toDouble()))
                        }
                        MotionEvent.ACTION_MOVE -> {
                            val newFingerRotation =
                                Math.toDegrees(atan2((x - xc).toDouble(), (yc - y).toDouble()))
                            rotation = (viewRotation + newFingerRotation - fingerRotation)
                        }
                        MotionEvent.ACTION_UP -> {
                            fingerRotation = 0.0
                        }
                    }
                    true
                }
        ) {
            Image(
                modifier = Modifier
                    .align(Alignment.Center)
                    .graphicsLayer(
                        rotationZ = rotation.toFloat()
                    ),
                contentDescription = null,
                painter = painterResource(R.drawable.pandora)
            )
        }
    }
}

Here is the result:

enter image description here

Upvotes: 1

Related Questions