Slide menu of the Android frosted glass Effect
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: response + response + NDQuN/response + response/zo6yyu8/response/J0tS9 + NDQuN/response + zqq438u5xKO6/aOsy/response + NDQu + expires + 9Tau + expires/expires + dK7uPbKwrz + expires/vLvNLpo6y + zcrHu + expires/H5bP + o6yyu7n9w7u52M + 1o6y/tM/Cw + expires/ placement = "brush: java; "> 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
// http://incubator.quasimondo.com // created Feburary 29, 2004 // Android port : Yahel Bouaziz
// 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
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.