https://kotlinlang.org logo
#compose
Title
# compose
v

Vinay Gaba

07/27/2020, 4:44 PM
I am trying to make a child composable non-interactive under certain conditions. I don’t know anything about the child composable and can’t change its definition either(so can’t simply pass a modifier to it). So I was trying to wrap it inside a Box and then applying the
rawPressStartGestureFilter
to it. This actually works but it also ends up interfering with the scroll of the screen that these composables are on (this is expected as this is how you’d expect this gesture filter to work). Is there a better way to accomplish this? Just using
tap
or
clickable
on the parent composable still propagates the touch to the child composable so I need a better way to intercept the touch while keeping the scroll functionality intact.
g

galex

07/27/2020, 4:47 PM
I’m doing a progress view on top of all children maybe that can help:
Copy code
Stack(Modifier.fillMaxSize()) {
        children?.invoke()
        Box(
            modifier = Modifier.fillMaxSize().tapGestureFilter {},
            backgroundColor = colorResource(id = R.color.transparent_black),
            gravity = ContentGravity.Center
        ) {
            CircularProgressIndicator()
        }
    }
v

Vinay Gaba

07/27/2020, 4:49 PM
oh that’s an interesting idea! Let me try stacking them!
I haven’t tried it yet but I think this might not work, unless Stack causes special logic that allows interception of gestures due to the order of composable. Will report back shortly!
g

galex

07/27/2020, 4:58 PM
If the most top box catches the tap, the children behind can’t be tapped on
v

Vinay Gaba

07/27/2020, 5:04 PM
With the same logic, I was trying this
Copy code
Box(modifier = Modifier.clickable{ //do Something }) {
    child()
}
It’s possible that this does not create an “gesture hierarchy” of sorts but Stack does? Do you happen to know?
g

galex

07/27/2020, 5:16 PM
Box is just a container AFAIK, when Stack really puts the children one on top of another so that’s why it works
I see what you mean, as if the parent composable of a Box should also “catch” the tap event instead of passing it to its children. I do not know enough about Compose to have an answer yet
v

Vinay Gaba

07/27/2020, 5:55 PM
So for me to get it to work with Stack, I need to know the size of the child composable so that I can place a Box on top of it exactly using Stack. So I made use of the
onPositioned
modifier but the size it returns is incorrect and it ends up occupying a lot more space than the space the child composable occupies.
Copy code
Stack {
    var size by state{ IntSize(0, 0) }
    Box(Modifier.onPositioned{size = it.size}) {
        childComposable
    }
    
    // Height it returns is almost double of what the child composable occupies.
    Box(Modifier.height(it.size.dp))
}
@Zach Klippenstein (he/him) [MOD] I know you’ve dabbled with onPositioned a few times. Were you noticing this as well where the size was off?
z

Zach Klippenstein (he/him) [MOD]

07/27/2020, 6:39 PM
I haven’t, but i haven’t played with it for a while. I think there’s also currently a bug where only one
onPositioned
callback will be fired if multiple nodes are re-layed out, so there are clearly bugs. I’d suggest filing a bug.
v

Vinay Gaba

07/27/2020, 6:48 PM
Thanks for the super prompt reply! Yeah does seem like a bug! I’ll file it!
There was a response of my ticket and apparently Stack has a special modifier called
matchParentSize
. So my example would have to look like this and it works!
Copy code
Stack {
    Box {
        childComposable()
    }
    Box(Modifier.matchParentSize())
}
@galex also Stack does intercept that child composable like you recommended! Thanks for the tip!
still looking for an answer for why I couldn’t just intercept the touch by applying a gesture to the parent Box without needing a Stack
9 Views