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

adjpd

09/08/2021, 10:42 PM
Dialog
and
DropDownMenu
unexpand and hide, respectively, when the user touches outside the composables. How can I implement this myself? I want to hide a composable if the user touches outside the composable.
The only idea I have is to make a custom class that extends
AbstractComposeView
so I can get access to
onTouchEvent
and check if the click is within the composable. Is there an easier way? It feels rather heavyweight to use an
AbstractComposeView
rather than the usual compose coding style for something fairly simple.
a

Alexandre Elias [G]

09/09/2021, 6:19 PM
you can use a
Modifier.pointerInput
for this. I suggest imitating the Scrim pattern in the built-in `ModalDrawer`: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]otlin/androidx/compose/material/Drawer.kt;l=374?q=ModalDrawer
a

adjpd

09/09/2021, 8:05 PM
So.... display a box that fills the screen and put a click listener on that? Or is there more to it that that?
a

Alexandre Elias [G]

09/09/2021, 8:39 PM
Basically that's all it is. But make sure to use a
Modifier.pointerInput
listener instead of a
Modifier.clickable
because the latter is designed for things like buttons, and will have undesirable effects on screen reader accessibility
a

adjpd

09/09/2021, 9:52 PM
My problem is that my component doesn't take up all the screen, the the scrim doesn't take up all the screen. I could move the scrim further up the composable hierarchy so it does take up all the space. But then my problem is that other click listeners further down the hierarchy will be called before the one on the scrim.
a

Alexandre Elias [G]

09/09/2021, 10:01 PM
Right.
ModalDrawer
is written in a such a way to take priority over the children (scrim as peer to content lambda instead of parent), I recommend imitating it.
a

adjpd

09/09/2021, 10:25 PM
Unless I'm mistaken, `ModalDrawer`'s scrim can intercept the events because it's composed after the other composables, but not interecept the events in the drawer, since it's composed before that. My component, unlike
ModalDrawer
, isn't on the root level with the other composables. So I'm unsure if this will work.
Unless this is the thing I'm misunderstanding. Semantics are still a mystery.
Copy code
.semantics(mergeDescendants = true) {
                contentDescription = closeDrawer
                onClick { onClose(); true }
            }
a

Alexandre Elias [G]

09/09/2021, 10:38 PM
Indeed, the way I would recommend to solve this is to refactor your code to get something on the root level. (Semantics are there to support screen readers but they don't affect ordinary touch input at all)
a

adjpd

09/09/2021, 10:43 PM
Thanks, that's the conclusion I'm arriving at. I'm slightly worried the
scrims
clicks my fall through the other composables but since that isn't the case, I assume, with
ModalDrawer
I guess it will work. Thanks Alexandre for your time. Hopefully I'll have a decent solution soon.
👍 1
Actually,
DropDownMenu
manages to do this with a
AbstractComposeView
(here precisely) but getting
AbstractComposeView
to work within a
Compose
project, rather than from the Android view system, is a new adventure...
2 Views