Home > Net >  Prevent dragging box out of the screen with Jetpack Compose
Prevent dragging box out of the screen with Jetpack Compose

Time:08-10

I have such code from here: https://developer.android.com/jetpack/compose/gestures

    Box(modifier = Modifier.fillMaxSize()) {
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }

        Box(
            Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .background(Color.Red)
                .size(120.dp) // makes it rectangle. wrap_content without it
                .align(Alignment.BottomEnd)
                .pointerInput(Unit) {
                    detectDragGestures { change, dragAmount ->
                        change.consume()
                        offsetX  = dragAmount.x
                        offsetY  = dragAmount.y
                    }
                }

        ) {
            // todo
        }
    }

So for end side of x I create something like this:

val newOffsetX = if ((offsetX   dragAmount.x) < 0) { offsetX   dragAmount.x } else { 0 }
offsetX = newOffsetX

But how can I found start of x and prevent my draggable box go out of screen? Is there a way to do it for both X and Y?

CodePudding user response:

If you align your draggable box with Alignment.TopStart you can coerce min and max width and height between 0 and parent size - box size

@Composable
private fun DragSample() {

    BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }

        val parentWidth = constraints.maxWidth
        val parentHeight = constraints.maxHeight
        Box(
            Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .background(Color.Red)
                .size(120.dp) // makes it rectangle. wrap_content without it
                .align(Alignment.TopStart)
                .pointerInput(Unit) {

                    val boxSize = this.size
                    detectDragGestures { _, dragAmount ->
                        offsetX = (offsetX   dragAmount.x).coerceIn(
                            0f,
                            parentWidth - boxSize.width.toFloat()
                        )
                        offsetY = (offsetY   dragAmount.y).coerceIn(
                            0f,
                            parentHeight - boxSize.height.toFloat()
                        )
                    }
                }

        ) {
            // todo
        }
    }
}

If you wish to start from Alignemnt.BottomEnd you should do it as

@Composable
private fun DragSample() {

    BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }

        val parentWidth = constraints.maxWidth
        val parentHeight = constraints.maxHeight
        Box(
            Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .background(Color.Red)
                .size(120.dp) // makes it rectangle. wrap_content without it
                .align(Alignment.BottomEnd)
                .pointerInput(Unit) {

                    val boxSize = this.size
                    detectDragGestures { _, dragAmount ->
                        offsetX = (offsetX   dragAmount.x).coerceIn(
                             boxSize.width.toFloat() -parentWidth,
                            0f
                        )
                        offsetY = (offsetY   dragAmount.y).coerceIn(
                             boxSize.height.toFloat() -parentHeight,
                            0f
                        )
                    }
                }

        ) {
            // todo
        }
    }
}
  • Related