Blur Background Behind AlertDialog

*爱你&永不变心* 提交于 2019-11-27 00:06:50
nitesh

This is How I have made Background of my Dialog blur

- Code and Concept HERE

- Github Project HERE

Steps

1) Take the Snapshot of Your Background using Below Code

private static Bitmap takeScreenShot(Activity activity)
    {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap b1 = view.getDrawingCache();
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;
        int width = activity.getWindowManager().getDefaultDisplay().getWidth();
        int height = activity.getWindowManager().getDefaultDisplay().getHeight();

        Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height  - statusBarHeight);
        view.destroyDrawingCache();
        return b;
    }

use it Like This Bitmap map=takeScreenShot(BlurImageView.this);// Your Actitvity Name

2) Call the Method Bitmap fast=fastblur(map, 10); Got it From Here

    public Bitmap fastblur(Bitmap sentBitmap, int radius) {
        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
            sir[1] = (p & 0x00ff00) >> 8;
        sir[2] = (p & 0x0000ff);
        rbs = r1 - Math.abs(i);
        rsum += sir[0] * rbs;
        gsum += sir[1] * rbs;
        bsum += sir[2] * rbs;
        if (i > 0) {
            rinsum += sir[0];
            ginsum += sir[1];
            binsum += sir[2];
        } else {
            routsum += sir[0];
            goutsum += sir[1];
            boutsum += sir[2];
        }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
            sir[1] = (p & 0x00ff00) >> 8;
            sir[2] = (p & 0x0000ff);

            rinsum += sir[0];
            ginsum += sir[1];
            binsum += sir[2];

            rsum += rinsum;
            gsum += ginsum;
            bsum += binsum;

            stackpointer = (stackpointer + 1) % div;
            sir = stack[(stackpointer) % div];

            routsum += sir[0];
            goutsum += sir[1];
            boutsum += sir[2];

            rinsum -= sir[0];
            ginsum -= sir[1];
            binsum -= sir[2];

            yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = ( 0xff000000 & pix[yi] ) | ( dv[rsum] << 16 ) | ( dv[gsum] << 8 ) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }

        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);
    }

3) Finally on Button click

btnblur.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {

                AlertDialog.Builder builder=new AlertDialog.Builder(BlurImageView.this,R.style.Theme_D1NoTitleDim);
                builder.setTitle("Content");
                builder.setMessage("CLICK OK to Exit");
                builder.setPositiveButton("ON", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        back_dim_layout.setVisibility(View.GONE);
                        dialog.cancel();
                    }
                });
                alert=builder.create();
                Bitmap map=takeScreenShot(BlurImageView.this);

                Bitmap fast=fastblur(map, 10);
                final Drawable draw=new BitmapDrawable(getResources(),fast);
                alert.getWindow().setBackgroundDrawable(draw);
                alert.show();
            }
        });

That's It Now You can see the Blur Image Behind You Activity

Hope this could Help full for AnyOne...

Try this way will help you i am using this

create a styles.xml

<style name="Theme.D1NoTitleDim" parent="android:style/Theme.Translucent">
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:background">@android:color/transparent</item>        
</style>

And then on your dialog

dialog = new Dialog(context,styles); 

This is working fine for me

For more i will suggest you to see this Example

Charuක

This solution from nitesh works like below

But if you cannot make your alert to center(like me) check my answer as well, which is Here

What i did was,

used two alertDialogs one is for the blur effect(for the use of getWindow()) and it does not get display now(I removed its setContentView / can use transparent background)

The other one is the real alertDialog got display after the blur effect

Out put

For a fast Blur and to solve the problem of Dialog to appear on the top of screen, I think there is an easier solution:

// Custom Dialog to be called in the Activity choosed.
public class CustomDialog {
    private Dialog dialog;

    public CustomDialog(AppCompatActivity activity) {
        dialog = new Dialog(activity);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        View viewCustomDialog = LayoutInflater.from(activity).inflate(R.layout.custom_dialog, null);
        dialog.setContentView(viewCustomDialog);

        RelativeLayout rootView = viewCustomDialog.findViewById(R.id.rootView);

        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.gravity = Gravity.CENTER;
        dialog.getWindow().setAttributes(layoutParams);

        // First get bitmap with blur filter applied, using the function blur presented here,  
        // or another function.
        // Activity parameter is the Activity for which you call dialog.show();
        Bitmap bitmap = Utils.blur(activity);

        // Get bitmap height.
        int bitmapHeight = bitmap.getHeight();

        dialog.setOnShowListener(dialogInterface -> {
            // When dialog is shown, before set new blurred image for background drawable, 
            // the root view height and dialog margin are saved.
            int rootViewHeight = rootView.getHeight();
            int marginLeftAndRight = dialog.getWindow().getDecorView().getPaddingLeft();

            // Set new blurred image for background drawable.
            dialog.getWindow().setBackgroundDrawable(new BitmapDrawable(builder.context.getResources(), bitmap));

            // After get positions and heights, recover and rebuild original marginTop position, 
            // that is (bitmapHeight - rootViewHeight) / 2.
            // Also recover and rebuild Dialog original left and right margin.
            FrameLayout.LayoutParams rootViewLayoutParams = (FrameLayout.LayoutParams)rootView.getLayoutParams();
            rootViewLayoutParams.setMargins(marginLeftAndRight, (bitmapHeight - rootViewHeight) / 2, marginLeftRight, 0);
        });

        dialog.show();
    }
}

Blur method:

public static Bitmap blur(AppCompatActivity activity) {
   Bitmap bitmap = Utils.takeScreenShot(activity);

   RenderScript renderScript = RenderScript.create(activity);

   // This will blur the bitmapOriginal with a radius of 16 and save it in bitmapOriginal
   final Allocation input = Allocation.createFromBitmap(renderScript, bitmap); // Use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
   final Allocation output = Allocation.createTyped(renderScript, input.getType());
   final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
   script.setRadius(16f);
   script.setInput(input);
   script.forEach(output);
   output.copyTo(bitmap);

   return bitmap;
}

TakeScreenShot method:

public static Bitmap takeScreenShot(AppCompatActivity activity) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bitmap = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;
    int[] widthHeight = getScreenSize(activity);
    Bitmap bitmapResult = Bitmap.createBitmap(bitmap, 0, statusBarHeight, widthHeight[0], widthHeight[1]  - statusBarHeight);
    view.destroyDrawingCache();
    return bitmapResult;
}   

GetScreenSize method:

public static int[] getScreenSize(Context context) {
    int[] widthHeight = new int[2];
    widthHeight[WIDTH_INDEX] = 0;
    widthHeight[HEIGHT_INDEX] = 0;

    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();

    Point size = new Point();
    display.getSize(size);
    widthHeight[WIDTH_INDEX] = size.x;
    widthHeight[HEIGHT_INDEX] = size.y;

    if (!isScreenSizeRetrieved(widthHeight)) {
        DisplayMetrics metrics = new DisplayMetrics();
        display.getMetrics(metrics);
        widthHeight[0] = metrics.widthPixels;
        widthHeight[1] = metrics.heightPixels;
    }

    if (!isScreenSizeRetrieved(widthHeight)) {
        widthHeight[0] = display.getWidth(); // deprecated
        widthHeight[1] = display.getHeight(); // deprecated
    }

    return widthHeight;
}   

private static boolean isScreenSizeRetrieved(int[] widthHeight) {
    return widthHeight[WIDTH_INDEX] != 0 && widthHeight[HEIGHT_INDEX] != 0;
}

And for use RenderScript (To blur), in the App's build.gradle you must add:

defaultConfig {
    ...     
    renderscriptTargetApi 19
    renderscriptSupportModeEnabled true
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!