Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
319 views
in Technique[技术] by (71.8m points)

android - AlertDialog with Blur background in position center

Question

Tried to blur (not DIM) the background of a Dialog.

and FLAG_BLUR_BEHIND is deprecated.

Approach is, take a screenshot form the currant view and blur it.Then attach to the background,When AlertDialog appears, and it works.

but AlertDialog is always in the Top not in the center.(check the image)

WindowManager.LayoutParams has no effect after attach .(before attach it to the background,alert can position to center, but after attaching the blur view to the background AlertDialog always go to the top )

How can I make my alert center in the screen?

below is code i tried,any guide will be appreciated ,

Displayed alert when i press back.

     @Override
        public void onBackPressed() {

            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
            builder.setTitle("Lets Blur");
            builder.setMessage("This is Blur Demo");
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });


            dialog = builder.create();

// this position alert in the CENTER
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            WindowManager.LayoutParams wmlp = dialog.getWindow().getAttributes();
            wmlp.gravity = Gravity.CENTER;
            dialog.show();

            new BlurAsyncTask().execute();

        }

        class BlurAsyncTask extends AsyncTask<Void, Integer, Bitmap> {


            protected Bitmap doInBackground(Void...arg0) {

                Bitmap map  = AppUtils.takeScreenShot(MainActivity.this);
                Bitmap fast = new BlurView().fastBlur(map, 10);
                return fast;
            }


            protected void onPostExecute(Bitmap result) {
                if (result != null){
                    final Drawable draw=new BitmapDrawable(getResources(),result);
                    Window window = dialog.getWindow();
// this position alert again in the TOP -- need to avoid that!
                    window.setBackgroundDrawable(draw);
                    window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
                    window.setGravity(Gravity.CENTER);
                    dialog.show();

                }

            }

Other classes

AppUtils

public class AppUtils {

    public 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;

        Display display = activity.getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;
        int height = size.y;


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

BlurView

public class BlurView {

    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);
    }
}

screen shot - this is the result i get- i want to make alert center but it stays on top this is the result i get- i want to make it center

Edit : Answer's Concept

  1. Take a screen shot
  2. Programmatically animate/blur/whatever effect to that screen shot
  3. Get currant window using a dialog witch does not have any content
  4. Attach screen shot with effect
  5. Display real view I wanted to display

Side Note: This can be used to attach any type of a background! blur.. dim..bright.. Just add the right method that accept a bitmap and return a bitmap with changes you want in BlurView class. I added a blur one.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Note: This screen background can be anything you have on it, what it does is take a screenshot of it and blur that finally set it as the background of the alertDialog with blur effect

Problem was alertDialog attached with that blur background was always on the top and i couldn't change that.

I came up with this solution.

I had to use 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 alert dialog got display after the blur effect.

MainActivity

public class MainActivity extends AppCompatActivity {

    private  AlertDialog dialogWhichDisplayAlert;
    private  Dialog fakeDialogUseToGetWindowForBlurEffect;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }


    @Override
    public void onBackPressed() {


        fakeDialogUseToGetWindowForBlurEffect = new Dialog(MainActivity.this);
        //  fakeDialogUseToGetWindowForBlurEffect.setContentView(R.layout.fakealert); // removed the content so not visible



        new BlurAsyncTask().execute();

    }

    class BlurAsyncTask extends AsyncTask<Void, Integer, Bitmap> {


        protected Bitmap doInBackground(Void...arg0) {

            Bitmap map  = AppUtils.takeScreenShot(MainActivity.this);
            Bitmap fast = new BlurView().fastBlur(map, 10);
            return fast;
        }


        protected void onPostExecute(Bitmap result) {
            if (result != null){
                final Drawable draw=new BitmapDrawable(getResources(),result);
                Window window = fakeDialogUseToGetWindowForBlurEffect.getWindow();
                window.setBackgroundDrawable(draw);
                window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
                window.setGravity(Gravity.CENTER);
                fakeDialogUseToGetWindowForBlurEffect.show();


                // real one
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
                builder.setTitle("Lets Blur");
                builder.setMessage("This is Blur Demo");
                builder.setCancelable(false);
                builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        fakeDialogUseToGetWindowForBlurEffect.dismiss();
                        dialog.cancel();
                    }
                });
                builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        fakeDialogUseToGetWindowForBlurEffect.dismiss();
                        dialog.cancel();
                    }
                });
                dialogWhichDisplayAlert = builder.create();

                // position real dialogWhichDisplayAlert using Gravity.CENTER;
                dialogWhichDisplayAlert.requestWindowFeature(Window.FEATURE_NO_TITLE);
                WindowManager.LayoutParams wmlp = dialogWhichDisplayAlert.getWindow().getAttributes();
                wmlp.gravity = Gravity.CENTER;
                dialogWhichDisplayAlert.show();

            }

        }
    }
}

[other classes used are same as the question]

style

<style name="AlertDialogCustom" parent="@android:style/Theme.Dialog">
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
        <item name="android:textSize">10sp</item>
    </style>

Out put

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...