Android frosted glass effect slide menu, android frosted glass

Source: Internet
Author: User
Tags vmin

Android frosted glass effect slide menu, android frosted glass
To achieve the goal, I believe everyone knows what the glass effect is, or Gaussian blur effect. As follows:
This is a transparent and Gaussian blur effect on the background. It looks like a frosted glass. In fact, it is not just a slide menu. As long as it is a view, it can be achieved theoretically, next we will achieve this effect. Step 1: Build the android studio framework I use. Therefore, it is very easy to create a project with a sliding menu. In the step of creating a project, execute this step, select Navigation Drawer Activity:
Android studio automatically creates a project with this slide to overwrite the current Activity menu. If it is Eclipse, You have to implement it by yourself, because the focus is not on the slide menu, don't talk about the implementation of the slide menu. You can go to the source code address below to see the source code. Step 2: before implementing the principle, you must first confirm the methods to achieve this effect. It is unrealistic to set a transparent background for Drawer and perform Gaussian blur on the background, because the obtained background is a Drawble object, unlike Bitmap objects that can perform Gaussian Fuzzy Operations, the second is only to blur the background, and the content of the view after the background cannot be displayed as Gaussian fuzzy. Therefore, this method is not feasible. Because the View behind the Drawer slide menu is changing in real time, the View can only be captured in real time for Gaussian blur and then used as the background of the Drawer. This operation can only be completed before the Drawer is drawn, because if it is captured and processed again, it will not only get stuck, but the captured image will not be needed now. Fortunately, in Android, there is such an event called PreDraw. Therefore, the callback is used to draw the previously called event. When the Android View is drawn, the next layer is first drawn, the observer who draws the View hierarchy. Before the painting, perform Gaussian blur on the desired View and set it to the background of the Drawer. This achieves the functions we need. Maybe I didn't express it clearly, but it doesn't matter. I can understand it by looking at the code parsing below. Step 3: implement the code first, you need to get the control of this slide menu. The slide menu generated by android studio is implemented using Fragment, so you can get it using the following code:

mNavigationDrawerFragment = (NavigationDrawerFragment)                getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
This NavigationDrawerFragment is the class implemented by our slide menu. You can leave it alone. Then you need to get the View in the Fragment, get the View observer, and register the PreDraw listening event:
mNavigationDrawerFragment.getView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {                    });
The OnPreDrawListener must implement the OnPreDraw method. In this method, the current View is implemented and Gaussian Blur is performed. First, find the root control and create a Bitmap object to save it.
private FrameLayout view;private Bitmap bitmap;
After the view is initialized, the view is started. The view method is as follows:
view.buildDrawingCache();bitmap = view.getDrawingCache();
In this way, the current view is saved in bitmap. Next we will perform Gaussian blur on the image. There are many Gaussian fuzzy algorithms on the Internet, so I will post one (copied):
    public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {        // Stack Blur v1.0 from        // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html        //        // Java Author: Mario Klingemann <mario at quasimondo.com>        // http://incubator.quasimondo.com        // created Feburary 29, 2004        // Android port : Yahel Bouaziz <yahel at kayenko.com>        // http://www.kayenko.com        // ported april 5th, 2012        // This is a compromise between Gaussian Blur and Box blur        // It creates much better looking blurs than Box Blur, but is        // 7x faster than my Gaussian Blur implementation.        //        // I called it Stack Blur because this describes best how this        // filter works internally: it creates a kind of moving stack        // of colors whilst scanning through the image. Thereby it        // just has to add one new block of color to the right side        // of the stack and remove the leftmost color. The remaining        // colors on the topmost layer of the stack are either added on        // or reduced by one, depending on if they are on the right or        // on the left side of the stack.        //        // If you are using this algorithm in your code please add        // the following line:        //        // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>        Bitmap bitmap;        if (canReuseInBitmap) {            bitmap = sentBitmap;        } else {            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];        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;            }        }        bitmap.setPixels(pix, 0, w, 0, 0, w, h);        return (bitmap);    }
The first parameter is an image that requires Gaussian blur. The second parameter can be interpreted as the Blur effect size. The third parameter indicates whether the bitmap can be reused. Okay. With the processed image, you can set it to the background of the Drawer .... Really? If you think about it carefully, of course it is not. The screenshot is the entire view, and our Drawer slides out slowly and may stop at any time, you cannot use a complete graph. You need to calculate the position of the screenshot image and set it to the Drawer position. For details, refer:
As can be seen from the figure, all the required parameters are related. That is to say, if one of the parameters can be obtained, other parameters can be obtained at the same time. The width of the Drawer can be fixed. In this example, it is set to 240. Now, you only need to obtain the position to which the slide is located to calculate all the parameters. In View, there is such a method called getLocationInWindow, which can obtain the position of the current View in the entire Window. As you can imagine, it must be a negative number, the width of the Drawer and the negative number can be used to calculate the display width. (In addition to getLocationInWindow, there are many other methods in View. You can study how to obtain the positions relative to various views ).
First, the location is obtained:
Int [] location = new int [2]; mNavigationDrawerFragment. getView (). getLocationInWindow (location); blur (bitmap, listView, location [0]); // only pass x coordinates
The blur function is used to process the location details. The uploaded listView is the only view in Fragment:
Private void blur (Bitmap bkg, View view, int width) {float scaleFactor = 4; // scale the image. after scaling, the blur effect is better. float radius = 2; Bitmap overlay = Bitmap. createBitmap (int) (view. getMeasuredWidth ()/scaleFactor), (int) (view. getMeasuredHeight ()/scaleFactor), Bitmap. config. ARGB_8888); Canvas canvas = new Canvas (overlay); canvas. translate (-view. getLeft ()/scaleFactor,-view. getTop ()/scaleFactor); canvas. scale (1/scaleFactor, 1/scaleFactor); Paint paint = new Paint (); paint. setFlags (Paint. FILTER_BITMAP_FLAG); float visibleWidth = slideMenuWidth + width; // visible width int visibleHeight = view. getHeight (); // visible height // The area intercepted from the view. The reason for + 10 and below-10 is that Gaussian blurred edges sometimes have shadows, therefore, increase the blur area Rect src = new Rect (0, 0, (int) (visibleWidth) + 10, visibleHeight); RectF dest = new RectF (-width-10, 0, slideMenuWidth, visibleHeight); // specifies the canvas of the region where the Drawer background is located. drawBitmap (bkg, src, dest, paint); overlay = ImageUtils. doBlur (overlay, (int) radius, true); // perform Gaussian blur if (Build. VERSION. SDK_INT <16) {// This method was used before 16 levels, and views were discarded in 16. setBackgroundDrawable (new BitmapDrawable (getResources (), overlay);} else {view. setBackground (new BitmapDrawable (getResources (), overlay ));}}
The whole event listening code is as follows:
MNavigationDrawerFragment. getView (). getViewTreeObserver (). addOnPreDrawListener (new ViewTreeObserver. onPreDrawListener () {@ Override public boolean onPreDraw () {if (bitmap = null) {view. buildDrawingCache (); bitmap = view. getDrawingCache ();} int [] location = new int [2]; mNavigationDrawerFragment. getView (). getLocationInWindow (location); blur (bitmap, listView, location [0]); // only returns true ;}});
Here, the glass effect of the slide menu is complete. Conclusion: If you can understand the method I used above, I believe that everyone will be able to draw a line by mistake to achieve the effects of all the view glass. The code in this example will be put on github. Here is the link address: Ghost.
Who has performed the android background frosted glass effect (similar to the folder opening Effect On Xiaomi desktop)

Hi!
You can go to the MIUI forum to communicate with developers,
I think this should be an animated effect.
In addition, the latest Android 4.4 native supports

 
Now, is it better for android to use the SlidingMenu open-source project to slide the menu bar, or is it better to use the Navigation Drawer that comes with android?

If you are learning the code, it is recommended to study the official version. However, SlidingMenu has many functions, such as controlling the background behind the menu when sliding out. It seems that the background of Navigation Drawer cannot be moved. It is a trend to replace open-source projects with official APIs, because everyone thinks that official interfaces are safe to use, but open-source projects may be more flexible.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.