How to combine clickable actions on parent and chi...
# compose
m
How to combine clickable actions on parent and children?
1
The case is simple - onClick on child (i.e. textview) and onLongClick on parent
combinedClickable
is not working as I expected
I want to use a long click on Text, but don’t want to pass an extra action here. So I’m looking for something like passing the touch event to parent
m
Thanks, but it’s still not working. I’m looking for something like this:
Copy code
Box(
        modifier = Modifier.background(Color.Green)
            .padding(16.dp)
            .pointerInput(Unit) {
                detectTapGestures(
                    onLongPress = {
                        Timber.e("onLongPress")
                    }
                )
            },
    ){
        Box(
            modifier = Modifier.background(Color.Red)
                .fillMaxSize()
                .pointerInput(Unit) {
                    detectTapGestures(
                        onPress = {
                            Timber.e("onPress Start")
                            val success = tryAwaitRelease()
                            Timber.e("onPress Stop $success")
                        }
                    )
                },
        )
    }
I mean I want to pass the event down, to the parent. So when I’ll execute long press on RED box and there’s no onLongPress callback I want to pass the event to the GREEN box and use it. Right now the event is consumed.
NestedLongPressDemo is not working for me too 🙂
c
+1, in Android can traverse its children and then call them through
performClick
, there seems to be no similar approach in Compose.
m
FYI @Ian Lake
@matvei Should I create a ticket for it, or it’s already planned?
m
We don't have plans to allow for this behaviour in the
detectTapGestures
implementation.
detect*Gestures
methods are terminal methods that allow for a predefined set of features corresponding to a gesture. Tap gestures consume down even, that being for a press, tap or long press. When the down even is consumed, parents of this node who are waiting for a down Unconsumed event won't be notified with this, therefore not triggering their callbacks. It would be surprising for button to allow parents to long-click through it by default. You can write your own gesture detector though, using different gesture passes or consumed/unconsumed logic you should be able to achieve your desired behaviour.
👍 1
m
I have tried to create my own gesture detectors for a scenario where I want to know the last time the user touched the screen, independent on where it’s being touched. Since a consumed event wont be sent to the parent (if I read the above correctly), it seems like the only solution is to create a layer on top of everything and listen to touches there, but as soon as I install a Modifier.PointerInput, even an empty one, it seems like the events are being consumed by this top layer and never reaches anything below it. Is there a compose solution to this problem?
m
Since a consumed event wont be sent to the parent (if I read the above correctly)
Every event will be sent fully through the pipeline from the root to the positively hit-tested child regarless of the comsumption. The event that is consumed by a child will be marked as such, that's it. For your problem it seems like you need to listen for any event that changed from down to up (lifted finger, mouse, etc) on the final pass, regardless of the comsumption
m
Hum. I tried to do this in a sibling container, i.e my root was a Box, and then i had one complex layout + a fillmaxsize Box inside the root Box. The fillmax was placed as either first or last component, and that approach did not work. I should probably put that logic inside the root Box instead. This will probably not work transparently with dialogs, but it's a start
m
Just like with views or any other tree-like system really, events do bubble up or down, not through siblings in the Z axis of the screen, so putting such logic on the root box might be a good way to go 👍