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


    感谢作者 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;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    decoreview监听如下:

    private final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                ··········
                return true;
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后,就是核心的绘制了。这里基于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;
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

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

    话说回来:

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

    注意

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

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

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

  • 相关阅读:
    【Linux】【网络】应用层协议:HTTPS
    如何成为一名超级高效的远程开发人员?
    虚拟现实VR技术在医疗行业的应用介绍
    # 【Android】逆向自动化
    简单聊聊ThreadLocal吧
    自定义命名不同类型文件,隐藏编号轻松整理,一键操作高效便捷!
    SpringBoot笔记1-架构介绍
    数据血缘全方位理解&实施指南
    这份Kubernetes学习笔记,看完直呼NB
    基于 ARM+FPGA+AD平台的多类型同步信号采集仪开发及试验验证(一)上位机设计
  • 原文地址:https://blog.csdn.net/motosheep/article/details/127730476