Reputation: 4115
I have two overlapping boxes. There's a blue box with an offset and low alpha transparency on top of a red box.
Box {
Box(Modifier
.size(200.dp)
.background(Color.Blue)
.clickable { Log.d("TAG", "I want to receive the clicks from the red box") }
) {}
Box(Modifier
.size(200.dp)
.offset(x = 20.dp)
.alpha(0.2F)
.background(Color.Red)
.clickable { Log.d("TAG", "I want my clicks to pass through to the blue box") }
) {}
}
How can the red box's clicks pass through to the blue box below?
(Real life scenario: I need this to happen during an animation, just as the box is fading out, and before it's moved elsewhere in the canvas, so the user can click on it just as it's nearly faded out, but click on the now visible composable underneath)
Upvotes: 6
Views: 3859
Reputation: 67248
You can do it using MutableInteractionSource and emitting events when Red Composable is touched
@Composable
private fun InteractionSample() {
val interactionSource = MutableInteractionSource()
val coroutineScope = rememberCoroutineScope()
val onClick: () -> Unit = {
Log.d("TAG", "I want to receive the clicks from the red box")
}
Box {
Box(
Modifier
.size(200.dp)
.background(Color.Blue)
.clickable(
interactionSource = interactionSource,
indication = rememberRipple(),
onClick = onClick
)
) {}
Box(
Modifier
.size(200.dp)
.offset(x = 190.dp)
.alpha(0.2F)
.background(Color.Red)
.pointerInput(Unit){
detectTapGestures(
onPress = {
Log.d("TAG", "I want my clicks to pass through to the blue box")
coroutineScope.launch {
val press = PressInteraction.Press(it)
interactionSource.emit(
press
)
interactionSource.emit(
PressInteraction.Release(press)
)
}
onClick()
}
)
}
) {}
}
}
Or implementing it via custom gesture will let ripple on screen till pointer is up or canceled by moving pointer outside Composable with
@Composable
private fun InteractionSample() {
val interactionSource = MutableInteractionSource()
val onClick: () -> Unit = {
Log.d("TAG", "I want to receive the clicks from the red box")
}
Box {
Box(
Modifier
.size(200.dp)
.background(Color.Blue)
.clickable(
interactionSource = interactionSource,
indication = rememberRipple(),
onClick = onClick
)
) {}
Box(
Modifier
.size(200.dp)
.offset(x = 190.dp)
.alpha(0.2F)
.background(Color.Red)
.pointerInput(Unit){
coroutineScope{
forEachGesture {
awaitPointerEventScope {
val down = awaitFirstDown()
val press = PressInteraction.Press(down.position)
onClick()
launch {
interactionSource.emit(
press
)
}
waitForUpOrCancellation()
launch {
interactionSource.emit(
PressInteraction.Release(press)
)
}
}
}
}
}
) {}
}
}
Upvotes: 5