About Android frosted glass implementation (3) recyclerview static frosted glass

background

Frosted glass is a love-hate topic in development. There are endless ways to play it, some dynamic and some static. Some are blurred in real time, and some only need to be blurred once. The frosted glass implementation in this article is static frosted glass.

development environment

win 10
as 4+
jdk 1.8

code

! ! ! The source code is at the end of the article! ! !

final effect

Insert image description here

Ideas

When you see the picture above, you must first observe the key points:
(1) The frosted glass area is "coherent" with the picture. That is to say, the frosted glass display content is consistent with the actual content, and visually it is the effect of "partial frosted glass" .
(2) The shape of frosted glass. It seems that the four corners of frosted glass are rounded. Therefore, it involves the drawing of rounded corners during the display process of frosted glass.

According to the key points, it can be concluded that the original image must be loaded first, and then set to the ImageView, and then obtain the image being displayed by the ImageView (set to the ImageView first, because it will be affected by its ScaleType attribute), and then customize the view to The acquired images can be processed.

accomplish

Now that the principle has been explained, how to implement it? List the steps:
(1) Display the picture on the background control
(2) Pass the picture after the background control is displayed into the custom frosted glass control
(3) Process, draw and display through canvas.
Let’s start with a detailed description of how to implement:

(1) Display the picture on the background control

This step is a routine operation. You can use glide, or you can just create a local image and set it into the background control. The demo here is configured through the ImageView xml attribute.

(2) Pass the image displayed by the background control into the custom frosted glass control

This involves the logic of "getting the picture of the display control". The specific implementation code is as follows:


    /**
     * 普通截图
     */
    public static void viewSnapShot(View view, ViewSnapListener listener) {
        try {
            //使控件可以进行缓存
            view.setDrawingCacheEnabled(true);
            //获取缓存的 Bitmap
            Bitmap drawingCache = view.getDrawingCache();
            //复制获取的 Bitmap
            drawingCache = Bitmap.createBitmap(drawingCache, 0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
            //关闭视图的缓存
            view.setDrawingCacheEnabled(false);
            view.destroyDrawingCache();
            if (drawingCache != null) {
                if (listener != null) {
                    listener.success(drawingCache);
                }
            } else {
                if (listener != null) {
                    listener.failed("draw cache is null");
                }
            }
        } catch (Exception e) {
            if (listener != null) {
                listener.failed(e.getMessage());
            }
        }
    }

Through this method, you can get the picture displayed in the ImageView control and return a bitmap object to the outside.

(3) Processing, drawing and display through canvas

This involves custom views. First, let’s look at the layout position set by xml. The code is as follows:

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="200dp">

            <ImageView
                android:id="@+id/thirdImg"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="centerCrop"
                android:src="@drawable/testblur" />

            <com.example.ktdemo.blur.blurwidget.BlurAlignBottomView
                android:id="@+id/ivBlurView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentBottom="true" />

        </RelativeLayout>

As you can see, the width and height of the custom frosted glass control BlurAlignBottomView are the same as the width and height of the background image display control.

Let’s talk about core implementation. Because the width and height are the same, it is much simpler to handle.
(1) Use the clipRect method to clip the area that does not need to be displayed
(2) Finally, blur the bitmap Gaussian and draw it on the canvas.

The code for Gaussian blurring of bitmap is as follows:

    public static Bitmap blur(Context context,int blurRadius, Bitmap srcBitmap) {
        try {
            float radius = Math.min(25,blurRadius);
            radius = Math.max(0,radius);
            Bitmap bitmap = srcBitmap.copy(srcBitmap.getConfig(), true);
            final RenderScript rs = RenderScript.create(context);
            final Allocation input = Allocation.createFromBitmap(rs, srcBitmap,
                    Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            final Allocation output = Allocation.createTyped(rs, input.getType());
            final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            script.setRadius(radius /* e.g. 3.f */);
            script.setInput(input);
            script.forEach(output);
            output.copyTo(bitmap);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return srcBitmap;
        }
    }

Just use native RenderScript blur.

The core code for clipping the display range and drawing bitmap is as follows:

            int mesWidth = getMeasuredWidth();
            int mesHeight = getMeasuredHeight();
            float radius = mBlurInfo.getRadius();

            Bitmap mSrcBitmap = mBlurInfo.getSrcBitmap();

            canvas.save();

            canvas.clipRect(0, mesHeight - mBlurInfo.getBlurHeight(), mesWidth, mesHeight);

            RectF canvasRectF = new RectF(0, mesHeight - mBlurInfo.getBlurHeight(), mesWidth, mesHeight);
            Path mPath = new Path();
            mPath.addRoundRect(canvasRectF, radius, radius, Path.Direction.CW);
            canvas.clipPath(mPath);

            Rect bitmapRect = new Rect(0, 0, mesWidth, mesHeight);
            canvas.drawBitmap(mSrcBitmap, null, bitmapRect, null);


            canvas.restore();
        }

Summarize. There are actually many practical implementation methods, and the implementation method in this article is just one of many methods. If you have a better method, please leave a message in the comment area.

Code address
Search for BlurAlignBottomView class

that’s all----------------------------------------------------------------------------

Guess you like

Origin blog.csdn.net/motosheep/article/details/130657018