如何在Jetpack Compose中实现全屏遮罩CircularProgressIndicator并屏蔽下层按钮
问题:Composable加载遮罩无法屏蔽下层视图点击
我想通过设置变量为true显示一个覆盖式Composable,中间包含小型CircularProgressIndicator,背景浅灰色半透明,同时屏蔽下层视图的输入。目前遮罩能正常显示,但下层按钮仍可被点击。代码如下:
@Composable fun ViewWithOverlaysView(mutableState: MutableState<Boolean>) { Box { Button(onClick = { println("Pressed!!") mutableState.value = true }) { Text("XX") } Spacer(modifier = Modifier.height(Dp(100f))) LoadingView(mutableState = mutableState) } } @Composable fun LoadingView(mutableState: MutableState<Boolean>) { if (mutableState.value) { Box( modifier = Modifier .fillMaxSize() .background( Color.LightGray.copy(alpha = 0.5f) ) ) { Center { CircularProgressIndicator() } } } }
请问如何让遮罩既保持半透明背景,又能屏蔽下方所有按钮的点击?
解决方案
问题根源是加载遮罩没有消费触摸事件,导致点击会透传到下层按钮。只需给LoadingView中的Box添加触摸事件拦截修饰符即可:
修改后的LoadingView代码:
@Composable fun LoadingView(mutableState: MutableState<Boolean>) { if (mutableState.value) { Box( modifier = Modifier .fillMaxSize() .background(Color.LightGray.copy(alpha = 0.5f)) // 拦截所有触摸事件,阻止向下传递 .pointerInput(Unit) { detectTapGestures { // 空实现,消费点击事件 } } ) { Center { CircularProgressIndicator() } } } }
原理说明
pointerInput(Unit) { detectTapGestures { } }会让遮罩接收并消费所有触摸事件,不再向下层视图传递,从而实现屏蔽输入的效果。
你也可以用另一种方式实现,效果一致:
.clickable(enabled = false, indication = null, interactionSource = remember { MutableInteractionSource() }) { }
将上述代码替换掉pointerInput部分即可,两种方式按需选择。
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

