I have a screen with a button. When I click on the...
# compose-desktop
k
I have a screen with a button. When I click on the button the screen refreshes, there’s a database call that takes a few seconds. During this refresh I want to show the user that something is happening and also stop the user interacting with this screen entirely. To do that I load a Box that contains a progress indicator, the Box completely covers the bottom screen. The bottom screen is visible through the Box, which is what I want. However any mouse moves are still picked up by the bottom screen, I have some ‘hover’ interactions on parts of the screen. Is there any way for the Box on top to ‘eat’ the mouse moves and prevent the bottom screen seeing them (apart from disabling an re-enabling all the interactions)?
a
Adding a
Modifier.pointerInput(Unit) {}
should do the job.
k
I assume you mean to place this on the top Box?That doesn’t work for me, the underlying buttons still get the mouse events
z
I cant recall the exact code, but I think you can get the desired behavior by also consuming the events inside pointerInput.
a
You need to also consume all the events in
Modifier.pointerInput(Unit)
That should be enough, but it’s not a 100% guarantee either. Other event listeners can choose to still process even consumed events.
z
You can also use
Modifier.focusProperties { canFocus = false }
to disable focus, which Im guessing impacts hover states?
a
Modifier.pointerInput(Unit) {}
is what
Surface
uses under the hood, and if it doesn't work, that should probably be considered to be a bug. Here's the related CL: https://android-review.googlesource.com/c/platform/frameworks/support/+/1719680
Also it works well for me on Android.
z
a
Hmm, that’s correct. It works not by consuming the events, but by simply making itself the target element of the events, so siblings behind it just don’t receive the event.
k
So the consensus is this is a bug, correct? If so should I raise it somewhere or does this: https://issuetracker.google.com/issues/301477279 from the link posted by @Zoltan Demant above cover everything?
a
I’m not convinced there is a bug. Can you post a reproducer?
k
OK, before I do that, in your earlier comment you said: “You need to also consume all the events in `Modifier.pointerInput(Unit)`” how do I do that? I’ve tried:
.pointerInput(Unit) {
this.awaitPointerEventScope {
// we should wait for all new pointer events
while (true) {
awaitPointerEvent(pass = PointerEventPass.Initial)
.changes
.forEach(PointerInputChange::consume)
}
}
}
a
I was mistaken. To prevent siblings (and their children) from receiving events you only need to add a
pointerInput
and cover the entire area with that element. No need to consume the events.
It needs to be like this:
Copy code
Box {  // common parent
    ContentBelow()  // content you want to prevent from receiving events
    Box(Modifier
        .fillMaxSize()
        .pointerInput(Unit) {}
    )
}
k
Aaarrrggghhh!! Apologies all, it does work, I was being an idiot