如何实现Jetpack Compose中上层Composable点击事件穿透到底层?
实现Composable点击事件穿透的方案
需求明确:上层半透明红色Box需将点击事件传递给下层蓝色Box,尤其适配动画淡出场景——当组件逐渐消失但仍在原位置时,让下方可见组件接收点击。
核心思路
Jetpack Compose中上层组件默认会消费点击事件,要实现穿透,需让上层组件不拦截事件,或手动允许事件向下传递。以下是两种实用方案:
方案一:用pointerInput替代clickable,返回PassThrough
通过自定义pointerInput处理点击逻辑,直接返回PointerEventPass.PassThrough,让事件继续向下传递给下层组件:
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,实现事件穿透 .pointerInput(Unit) { awaitPointerEventScope { awaitFirstDown() PointerEventPass.PassThrough } } ) {} }
方案二:移除上层clickable,添加空pointerInput
如果上层不需要响应任何点击逻辑,直接去掉clickable,并通过空pointerInput确保组件不消费事件:
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) // 空pointerInput,允许事件向下传递 .pointerInput(Unit) { } ) {} }
动画场景适配
针对淡出动画场景,可根据动画进度动态控制是否开启穿透:
val alpha by animateFloatAsState(targetValue = if (isFadingOut) 0f else 0.2f) val shouldPassThrough by remember { derivedStateOf { alpha < 0.5f } } Box { Box(Modifier .size(200.dp) .background(Color.Blue) .clickable { Log.d("TAG", "Received click from red box area") } ) {} Box(Modifier .size(200.dp) .offset(x = 20.dp) .alpha(alpha) .background(Color.Red) .then( if (shouldPassThrough) { Modifier.pointerInput(Unit) { } } else { Modifier.clickable { Log.d("TAG", "Red box handles click") } } ) ) {} }
淡出过程中(alpha低于阈值)点击自动穿透到下层;组件完全显示时,可正常响应自身点击。
内容的提问来源于stack exchange,提问作者mmm111mmm
相关产品推荐
相关产品推荐

