Android 12 RenderEffect模糊作用于整个视图而非BottomSheet背景问题
问题原因
- 你调用
((View) bottomNav.getParent()).setRenderEffect()时,bottomNav.getParent()就是BottomSheet的根容器,模糊效果会作用于该容器下所有子View,自然包括弹窗本身的文字和按钮。 - 你用
FLAG_BLUR_BEHIND不生效的常见原因有三个:- 弹窗的主题未配置透明Window背景属性
- 设置代码在
show()方法之前执行,Window属性未生效 - 模糊半径太小效果不明显,或设备系统关闭了模糊特效开关
解决方案
方案1:修复系统Window模糊方案(Android12+)
首先修改你的BottomSheetDialogTheme主题,新增以下属性:
<item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item>
然后调整代码执行顺序,在弹窗show()之后再设置模糊属性:
bottomSheetData.show(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { Window window = bottomSheetData.getWindow(); if (window != null) { window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); WindowManager.LayoutParams params = window.getAttributes(); params.setBlurBehindRadius(20); // 可自行调整半径,数值越大模糊越强 params.dimAmount = 0.2f; // 搭配半透明蒙层效果更好 window.setAttributes(params); } }
方案2:模糊Activity底层布局(兼容性更高,Android12+)
直接对弹窗下的Activity页面做模糊,完全不会影响弹窗本身的显示效果:
// 弹窗显示时给Activity根布局加模糊 bottomSheetData.setOnShowListener(dialog -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { View activityRoot = getWindow().getDecorView().findViewById(android.R.id.content); activityRoot.setRenderEffect(RenderEffect.createBlurEffect(15f, 15f, Shader.TileMode.CLAMP)); } }); // 弹窗关闭时清除模糊效果 bottomSheetData.setOnDismissListener(dialog -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { View activityRoot = getWindow().getDecorView().findViewById(android.R.id.content); activityRoot.setRenderEffect(null); } });
如果需要兼容Android12以下的版本,可以使用RenderScript或者第三方模糊库实现截图模糊效果,性能略低于原生API。
内容的提问来源于stack exchange,提问作者gcantoni
相关产品推荐
相关产品推荐

