Is this meant to happen? Does `Modifier.verticalSc...
# compose
a
Is this meant to happen? Does
Modifier.verticalScroll()
consume clicks normally?
Copy code
Box {
    Box(Modifier.fillMaxSize().clickable { warnln { "Click!" } }) // <- never gets clicked
    Box(Modifier.fillMaxSize().verticalScroll(rememberScrollState()))
}
I can imagine why it might be intended, but it's weird from an dev POV. Ended up working around it by making the scrollable's content clickable instead and treat it as my bg
n
what is meaning of POV
k
Point of view
1
a
both use
fillMaxSize()
. Since they stack, the scrollable Box is on top, preventing clicks from reaching the clickable Box. i think !!
☝️ 1
l
This is because pointer input events aren’t shared with siblings. If you flip the order of the modifiers / boxes, then the other modifier would receive all events - it’s not about the specific modifier’s behavior. If you moved one of the modifiers to be on the parent box instead of a sibling it should resolve it also
a
it’s not about the specific modifier’s behavior
I'm confused. If that's not the case why does this gets clicked?
Copy code
Box {
                Box(Modifier.fillMaxSize().clickable { warnln { "Click!" } }) // <- gets clicked
                Box(Modifier.fillMaxSize())
            }
l
I meant that any pointerInput modifier should have the same effect
So if you just add an empty pointerInput() modifier on the second box, or clickable, or scrollable, etc
a
ah gotcha. are u saying that the verticalScroll uses
pointerInput()
and as a result it doesnt share the event with the siblings?
l
yeah exactly. The simplest case is just:
Copy code
Box {
    Box(Modifier.pointerInput())
    Box(Modifier.pointerInput())
}
By default, only one of these can receive any events
a
This somewhat makes sense. I know that you can consume events like this:
Copy code
Modifier.pointerInput(Unit) {
    awaitPointerEventScope {
        while (true) {
            val event = awaitPointerEvent(
                pass = PointerEventPass.Main
            )

            event.changes.forEach { it.consume() }
        }
    }
}
If just setting the pointerInput() consumes the event, why is there a way to consume changes? is that a different thing?
l
It’s a bit different, the case I mentioned is just for siblings - and often you cannot control the hierarchy in this way from a component so you can’t really use that meaningfully. Also, the order of siblings matters, so if you change the order then the sibling that receives the event changes
Consuming events is for a parent - child relationship, you can consume events to let other pointer input nodes know that you have already used this event, and they shouldn’t look at it
a
perfect. that clarified things. thanks Louis
k
For the parent-child propagation, https://developer.android.com/develop/ui/compose/touch-input/pointer-input/understand-gestures might be interesting, especially the "touchSlop" part which helps to decide if the user scrolls or just clicks