You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为居中显示的PopupWindow实现背景模糊效果?

我来给你几个实用的解决方案,帮你搞定在Fragment的RecyclerView Adapter里触发居中PopupWindow时,没法截取Activity UI做模糊背景的问题:

方案1:通过View获取根视图并截图

不需要直接持有Activity引用,你可以从点击的列表项View入手,拿到整个界面的根视图后再截图模糊,步骤如下:

  1. 从点击的item View中获取根视图(整个Activity的界面容器)
  2. 监听根视图的绘制完成事件,避免截图为空
  3. 截取根视图并做模糊处理,最后设置为PopupWindow的背景

代码示例:

holder.itemView.setOnClickListener(v -> {
    // 获取整个界面的根视图
    View rootView = v.getRootView();
    
    // 监听视图绘制完成,确保截图时界面已渲染完毕
    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // 移除监听,防止重复触发
            rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            
            // 截取根视图生成Bitmap
            Bitmap bitmap = Bitmap.createBitmap(rootView.getWidth(), rootView.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            rootView.draw(canvas);
            
            // 用你之前的fast blur工具处理模糊
            Bitmap blurredBitmap = fastBlur(bitmap, 10); // 10为模糊半径,可调整
            
            // 将模糊后的Bitmap转为Drawable作为弹窗背景
            Drawable blurredBg = new BitmapDrawable(v.getResources(), blurredBitmap);
            
            // 创建并显示居中PopupWindow
            PopupWindow popupWindow = new PopupWindow(contentView, width, height);
            popupWindow.setBackgroundDrawable(blurredBg);
            popupWindow.showAtLocation(rootView, Gravity.CENTER, 0, 0);
        }
    });
});

这个方案的核心是利用View的getRootView()方法,绕开了直接获取Activity的限制,完美适配Fragment+Adapter的场景。

方案2:单独添加全局模糊遮罩层

如果不想把模糊效果绑定到PopupWindow的背景上,可以先给整个屏幕添加一层模糊遮罩,再显示PopupWindow,弹窗消失时移除遮罩:

  1. 通过Context获取WindowManager
  2. 创建覆盖全屏的模糊View,添加到WindowManager
  3. 显示PopupWindow,设置消失监听移除遮罩

代码示例:

holder.itemView.setOnClickListener(v -> {
    Context context = v.getContext();
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    
    // 创建模糊遮罩View
    View blurMask = new View(context);
    // 先截取根视图并模糊
    Bitmap rootBitmap = getRootBitmap(v); // 复用方案1的截图逻辑
    Bitmap blurredBitmap = renderScriptBlur(context, rootBitmap);
    blurMask.setBackground(new BitmapDrawable(context.getResources(), blurredBitmap));
    
    // 设置遮罩的布局参数
    WindowManager.LayoutParams maskParams = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
            PixelFormat.TRANSLUCENT
    );
    windowManager.addView(blurMask, maskParams);
    
    // 创建并显示PopupWindow
    PopupWindow popupWindow = new PopupWindow(contentView, width, height);
    popupWindow.setOutsideTouchable(true);
    // 弹窗消失时移除遮罩
    popupWindow.setOnDismissListener(() -> windowManager.removeView(blurMask));
    popupWindow.showAtLocation(v.getRootView(), Gravity.CENTER, 0, 0);
});

// 用RenderScript实现高效模糊的工具方法
private Bitmap renderScriptBlur(Context context, Bitmap inputBitmap) {
    RenderScript rs = RenderScript.create(context);
    Allocation input = Allocation.createFromBitmap(rs, inputBitmap);
    Allocation output = Allocation.createTyped(rs, input.getType());
    ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
    
    blurScript.setRadius(10f);
    blurScript.setInput(input);
    blurScript.forEach(output);
    
    output.copyTo(inputBitmap);
    rs.destroy();
    return inputBitmap;
}

这个方案的优势是模糊层和PopupWindow完全分离,适合需要动态调整模糊效果的复杂场景。

方案3:用第三方库简化实现

如果不想自己写截图和模糊的逻辑,可以用成熟的第三方库(比如BlurView),它已经封装了所有细节,只需要简单配置即可:

  1. 添加库依赖(以Gradle为例):
implementation 'com.github.Dimezis:BlurView:version' // 替换为最新版本号
  1. 在PopupWindow的布局中添加BlurView作为根布局:
<com.jakewharton.rxbinding4.view.RxView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.google.android.material.blur.BlurView
        android:id="@+id/popup_blur_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <!-- 你的弹窗内容布局 -->
        
    </com.google.android.material.blur.BlurView>
</com.jakewharton.rxbinding4.view.RxView>
  1. 在Adapter的点击事件中配置BlurView:
holder.itemView.setOnClickListener(v -> {
    View contentView = LayoutInflater.from(v.getContext()).inflate(R.layout.popup_layout, null);
    BlurView blurView = contentView.findViewById(R.id.popup_blur_view);
    
    // 配置模糊参数,指定要模糊的根视图
    blurView.setupWith(v.getRootView())
            .setBlurAlgorithm(new RenderScriptBlur(v.getContext()))
            .setBlurRadius(10f)
            .setBlurAutoUpdate(true);
    
    // 创建并显示PopupWindow
    PopupWindow popupWindow = new PopupWindow(contentView, width, height);
    popupWindow.setOutsideTouchable(true);
    popupWindow.showAtLocation(v.getRootView(), Gravity.CENTER, 0, 0);
});

这个方案最省心,库已经处理了截图、模糊、适配等所有问题,适合快速开发。

内容的提问来源于stack exchange,提问作者JimJay Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:34:30