whatsapp sticker maker editor with kotlin and jetpack compose

128 views Asked by At

I want to make a sticker maker application with Kotlin and Compose, but I'm stuck in making the sticker editor because I want it to be like the picture I posted below, but I couldn't find a solution. I want this editor to move, zoom, rotate, With just one finger.

picture

Exactly like this gif I posted

like this lib https://github.com/wuapnjie/StickerView but i wnat kotlin and compose

I tried to make it using the articles and previous Stack Overflow questions but it didn't work as I expected

@ExperimentalComposeUiApi
@Composable
fun OneFinger() {


    var viewRotation = remember { 0.0 }
    var fingerRotation = remember { 0.0 }
    var rotation by remember {
        mutableStateOf(0.0)
    }

    var centerX by remember {
        mutableStateOf(0f)
    }

    var centerY by remember {
        mutableStateOf(0f)
    }

    var touchX by remember {
        mutableStateOf(0f)
    }

    var touchY by remember {
        mutableStateOf(0f)
    }

    var translationX by remember {
        mutableStateOf(0f)
    }

    var translationY by remember {
        mutableStateOf(0f)
    }

    var sizeTouchX by remember {
        mutableStateOf(0f)
    }

    var sizeTouchY by remember {
        mutableStateOf(0f)
    }

    var size by remember {
        mutableStateOf(85)
    }

    BoxWithConstraints(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .size(400.dp)
            .background(Color.White)
    ) {

        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .graphicsLayer(
                    translationX = translationX,
                    translationY = translationY,
                )
        ) {

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier
                    .rotate(rotation.toFloat())
            ) {
                Box(
                    modifier = Modifier
                        .size((115 + (size - 85)).dp)
                        .border(
                            border = BorderStroke(0.5.dp, Color.Gray),
                            shape = RectangleShape
                        )
                )

                Box(
                    modifier = Modifier
                        .size((135 + (size - 85)).dp)
                ) {
                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .align(Alignment.BottomStart)
                            .onGloballyPositioned {
                                val windowBounds = it.boundsInWindow()
                                centerX = (windowBounds.size.width / 2f)
                                centerY = (windowBounds.size.height / 2f)
                                Log.e("error1" , "centerX = $centerX and center y = $centerY")
                            }
                            .pointerInteropFilter { event ->
                                touchX = event.x
                                touchY = event.y
                                when (event.action) {
                                    MotionEvent.ACTION_DOWN -> {

                                        viewRotation = rotation

                                        fingerRotation = Math.toDegrees(
                                            atan2(
                                                (touchX - centerX).toDouble(),
                                                (centerY - touchY).toDouble()
                                            )
                                        )
                                    }

                                    MotionEvent.ACTION_MOVE -> {
                                        val newFingerRotation = Math.toDegrees(
                                            atan2(
                                                (touchX - centerX).toDouble(),
                                                (centerY - touchY).toDouble()
                                            )
                                        )

                                        rotation =
                                            (viewRotation + newFingerRotation - fingerRotation)
                                    }

                                    MotionEvent.ACTION_UP -> {
                                        fingerRotation = 0.0
                                    }
                                }
                                true
                            }
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.baseline_replay_24),
                            contentDescription = null,
                            modifier = Modifier
                                .align(Alignment.BottomStart)
                                .clip(CircleShape)
                                .background(BlackGray)

                        )
                    }

                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .align(Alignment.BottomEnd)
                            .pointerInput(Unit) {
                                awaitEachGesture {
                                    awaitFirstDown()
                                    do {
                                        val event = awaitPointerEvent()
                                        val offset = event.calculatePan()
                                        sizeTouchX += offset.x
                                        sizeTouchY += offset.y
                                        val currentDistance = sqrt(
                                            sizeTouchX.pow(2) + sizeTouchY.pow(2)
                                        )

                                        size = currentDistance.roundToInt()


                                    } while (event.changes.any { it.pressed })
                                }
                            }
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.baseline_open_in_full_24),
                            contentDescription = null,
                            modifier = Modifier
                                .align(Alignment.BottomEnd)
                                .clip(CircleShape)
                                .background(BlackGray)
                        )
                    }
                }


                Box {
                    Image(
                        modifier = Modifier.size(size.dp),
                        contentDescription = null,
                        painter = painterResource(R.drawable.ic_launcher_background)
                    )
                }
            }

            Box(
                modifier = Modifier
                    .size((105 + (size - 85)).dp)
                    .pointerInput(Unit) {
                        detectDragGestures { change, dragAmount ->
                            translationY += dragAmount.y
                            translationX += dragAmount.x
                            change.consume()
                        }
                    }
            )
        }
    }
}

and in main screen

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun MainScreen() {

    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .background(Color.LightGray)
            .fillMaxSize()
    ) {
        OneFinger()
    }
}
0

There are 0 answers