Jetpack Compose detectDragGestures seems to be working only when Canvas modifier is set to fillMaxSize or matchParentSize inside a Box

Viewed 192

I am creating a project where I have to move around Canvas elements(circles and lines) on drag gestures. I am using a Box composable to put different Canvas(s) inside it. And then with the help of pointerInput modifier I want to detect drag Gesture and hopefully achieve the behaviour I want.

Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(paddingValue),
        contentAlignment = Alignment.Center
    ){
      Canvas(modifier = Modifier
                .pointerInput(Unit) {
                    detectDragGestures { change, dragAmount ->
                        change.consumeAllChanges()
                        centerOffSet = centerOffSet.plus(dragAmount)
                    }
                }
            ) {
                drawCircle(
                    color = Color.White,
                    center = centerOffSet,
                    radius = radiusValue
                )
            }
}

The problem I'm facing is that when I set the Canvas modifier to .matchParentSize() or .fillMaxSize(), I'm able to drag the circle but this makes the whole surface of the Box a touch target, which is not desired, using the .wrapContentSize() modifier is not working. Is there something I'm missing here?

1 Answers

Canvas is a Spacer with Modifier.drawBehind so it needs dimensions to have bounds.

@Composable
fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) =
    Spacer(modifier.drawBehind(onDraw))

So you need to assign a Modifier that sets its dimensions. It's not correct that it s seems to be working only when Canvas modifier is set to fillMaxSize or matchParentSize inside a Box.

You can make it work any Modifier.size(), Modifier.fillX() or Modifier.matchParentSize().

It draws even without any dimensions while its Size is Size.Zero, or outside of your Canvas dimensions if you set one. You can see its bounds when you set a border or use Modifier.clipToBounds() which clips your drawing outside its bounds with no dimension assignment you will see that nothing is being drawn. Or you can check Canvas size from DrawScope to see what's its Size is.

The problem I'm facing is that when I set the Canvas modifier to .matchParentSize() or .fillMaxSize(), I'm able to drag the circle but this makes the whole surface of the Box a touch target

This is expected behavior.

In you question i didn't get how you exactly want to divide Box area to Canvases but you need to assign a Size according to your needs.

Related