美文网首页
关于安卓毛玻璃实现(一)动态毛玻璃

关于安卓毛玻璃实现(一)动态毛玻璃

作者: motosheep | 来源:发表于2022-11-06 14:28 被阅读0次

    动态毛玻璃实现

    感谢作者 RealtimeBlurView

    !!!源码链接在最后!!!

    问题

    在不断变化的背景中,实现毛玻璃

    思路

    (1)监听布局绘制,动态捕获布局的画像
    (2)实时对布局的图片进行高斯模糊,绘制

    实现

    (1)监听实现,只需要在监听的布局中,设置好监听回调即可。
    监听为ViewTreeObserver.OnPreDrawListener。设置好以后,布局绘制信息发生改变的时候,都会回调。

    这里选择获取页面的decoreview作为监听的布局

        protected View getActivityDecorView() {
            Context ctx = getContext();
            for (int i = 0; i < 4 && !(ctx instanceof Activity) && ctx instanceof ContextWrapper; i++) {
                ctx = ((ContextWrapper) ctx).getBaseContext();
            }
            if (ctx instanceof Activity) {
                return ((Activity) ctx).getWindow().getDecorView();
            } else {
                return null;
            }
        }
    

    decoreview监听如下:

    private final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                ··········
                return true;
            }
        };
    

    然后,就是核心的绘制了。这里基于decoreview,通过设置一层canvas进行独立的绘制,核心方法如下:

        private final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (!canBlur()) {
                    return true;
                }
                if (!blurInterval()) {
                    return true;
                }
                final int[] locations = new int[2];
                Bitmap oldBmp = mBlurredBitmap;
                View decor = mDecorView;
                if (decor != null && isShown() && prepare() && checkScreenLocation(decor)) {
                    boolean redrawBitmap = mBlurredBitmap != oldBmp;
                    oldBmp = null;
                    decor.getLocationOnScreen(locations);
                    int x = -locations[0];
                    int y = -locations[1];
                    getLocationOnScreen(locations);
                    x += locations[0];
                    y += locations[1];
                    // just erase transparent
                    mBitmapToBlur.eraseColor(mOverlayColor & 0xffffff);
                    int rc = mBlurringCanvas.save();
                    mIsRendering = true;
                    RENDERING_COUNT++;
                    try {
                        mBlurringCanvas.scale(1.f * mBitmapToBlur.getWidth() / getWidth(), 1.f * mBitmapToBlur.getHeight() / getHeight());
                        mBlurringCanvas.translate(-x, -y);
                        if (decor.getBackground() != null) {
                            decor.getBackground().draw(mBlurringCanvas);
                        }
                        decor.draw(mBlurringCanvas);
                    } catch (StopException e) {
                    } finally {
                        mIsRendering = false;
                        RENDERING_COUNT--;
                        mBlurringCanvas.restoreToCount(rc);
                    }
                    if (canBlur()) {
                        blur(mBitmapToBlur, mBlurredBitmap);
                    }
                    if ((redrawBitmap || mDifferentRoot) && canBlur()) {
                        Log.d(TAG, "onPreDraw identify: " + mIdentify);
                        postInvalidate();
                    }
                }
    
                return true;
            }
        };
    

    可以看出,这里直接通过屏幕高度方法 getLocationOnScreen();进行坐标获取,在进行坐标计算,bitmap截取,绘制,实现了动态毛玻璃的效果。但是,这种相关仅仅使用于非视频层级,视频播放层级(surfaceview),目前还是没有毛玻璃效果的,暂未想到解决方案。

    话说回来:

    实现毛玻璃的方法,是使用安卓原生的api:RenderScript进行实现。这里没啥好说的。

    注意

    在recyclerview中,实现动态毛玻璃,需要特别适配,目前只适配了出现时的item显示毛玻璃,其余适配将会放到下一个博客,敬请期待!!

    that's all-------------------------------------------------

    (代码地址--库libpicblur)[https://gitee.com/motosheep/androidutils-github]

    相关文章

      网友评论

          本文标题:关于安卓毛玻璃实现(一)动态毛玻璃

          本文链接:https://www.haomeiwen.com/subject/uhgbtdtx.html