简体   繁体   中英

Prevent dragging box out of the screen with Jetpack Compose

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 ?

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
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM