侧边栏高斯模糊(二)

  • 闲言碎语

很长一段时间没来写博客了,绝大部分是自己的惰性导致,当然工作压力大也没什么想写的也是一个因素.现在这个点,睡不着,又感觉有说不完的话,于是乎,拿出电脑要把灵感全倒出来...

还是接着前面说过的侧边栏高斯模糊的效果,今天说的效果要好很多,这里说的侧边栏高斯模糊具体指的是侧拉出多少宽度,就看到下面有多少区域模糊.今天录个清晰点的屏,上需求效果图:

 

  • 分析思路

先引入一个"图层"的概念,约定视图按照显示层级划分,由里向外依次为 主背景图层、模糊图层、侧边栏图层;

后面的主背景会改变(先忽略播放条的滚动),每次展开抽屉时看到的模糊图层视图基本不一样,这就要求能动态获取主背景的快照 -->view有个getDrawingCache()的方法可以获取屏幕快照

模糊效果      -- > 给特哈博上找星多的,看下已知缺陷和Issue维护情况,一般就是它了

是拉出多少,显示多少宽度的模糊,实时获取屏幕快照? too naive!这本来就是个费时耗gpu的操作,别想太多了.

那怎么办?想到一个以假乱真的办法,打肿脸充下胖子~

先把模糊图片生成了,再一点一点滑出来. -->关联cover_left.setVisibily()设置控件的可见性(可见 不可见)  setLayoutParams()设置控件的布局参数(宽 高)

处理时机,什么时候给主背景来一套截屏裁剪模糊的操作?主背景改变的时候?侧边栏开始展开的时候?如何判断主背景渲染完成的时机?侧边栏点击展开可以掌握,那侧拉操作呢?

 

  • 实现步骤
    1. 提前获取屏幕快照 -->裁剪与侧边栏同宽高的区域 --> 生成模糊图片 -->设置模糊图层不可见
    2. 设置DrawerLayout(也可自己实现侧边栏)的抽屉监听,滑动多少,就把模糊图层区域的宽度设置为多少(当然了,只要开始滑动了就设置其可见)
    3. 关键操作一:cover_leftblur.setScaleType(ImageView.ScaleType.MATRIX);matrix表示原图从ImageView的左上角开始绘制,如果原图大于ImageView,那么多余的部分则剪裁掉,如果原图小于ImageView,那么对原图不做任何处理

    关键操作二:                                            //把大象装进冰箱分三步走

           ViewGroup.LayoutParams layoutParams = cover_leftblur.getLayoutParams();    // 1.把冰箱门打开
           layoutParams.width = (int) (slip_per * CommonUtils.dip2px(getContext(), 531)); // 2.把大象装进去
           cover_leftblur.setLayoutParams(layoutParams);
                                           
//3.把冰箱门关上

  • 代码

     Talk is cheap, show me the code.

    

             mainActivity.getMain_content().setDrawingCacheEnabled(true);//打开view cache的开关
                    mainActivity.getMain_content().buildDrawingCache();      //生成cache
                    Bitmap drawingCache = mainActivity.getMain_content().getDrawingCache(); //获取生成cache的bitmap
           //根据这个bitmap生成一张与侧边栏同宽高的bitmap 参数2,3,4,5 分别为在屏幕上显示的左上右下 Bitmap cropBitmap
= Bitmap.createBitmap(drawingCache, 0, 0, CommonUtils.dip2px(getContext(), 531), mainActivity.getMain_content().getHeight(), null, false); mainActivity.getCover_leftblur().setImageBitmap(BlurKit.getInstance().blur(cropBitmap, 8));//BlurKit是个开源的模糊框架,据此生成模糊图片,并设置到模糊视图上 mainActivity.getCover_leftblur().setVisibility(View.INVISIBLE); //先藏起来,开始滑动再露出来 mainActivity.getCover_leftblur().destroyDrawingCache();      //销毁cache mainActivity.getMain_content().setDrawingCacheEnabled(false);  //关闭view cache的开关 drawerLayout.openDrawer(Gravity.LEFT, true);            //展开抽屉

 

  cover_leftblur = (ImageView) findViewById(R.id.cover_leftblur);
        cover_leftblur.setScaleType(ImageView.ScaleType.MATRIX);//很关键

 

//得到开关对象
        mToggle = new ActionBarDrawerToggle(this, mDrawlayout, R.string.open, R.string.close) {
            /**
             * 当抽屉滑动状态改变的时候被调用
             * 状态值是STATE_IDLE(闲置--0), STATE_DRAGGING(拖拽的--1), STATE_SETTLING(固定--2)中之一。
             * 抽屉打开的时候,点击抽屉,drawer的状态就会变成STATE_DRAGGING,然后变成STATE_IDLE
             */
            @Override
            public void onDrawerStateChanged(int arg0) {
                Log.i("drawer的状态", "" + arg0);
            }

            /**
             * 当抽屉被滑动的时候调用此方法
             * arg1 表示 滑动的幅度(0-1)
             */
            @Override
            public void onDrawerSlide(View arg0, float arg1) {
                cover_leftblur.setVisibility(View.VISIBLE);
                ViewGroup.LayoutParams layoutParams = cover_leftblur.getLayoutParams();
                layoutParams.width = (int) (arg1 * CommonUtils.dip2px(getContext(), 531));
                cover_leftblur.setLayoutParams(layoutParams);
            }

            /**
             * 当一个抽屉被完全打开的时候被调用
             */
            @Override
            public void onDrawerOpened(View arg0) {
                Log.i("drawer", "抽屉被完全打开了!");

            }

            /**
             * 当一个抽屉完全关闭的时候调用此方法
             */

            @Override
            public void onDrawerClosed(View arg0) {
                Log.i("drawer", "抽屉被完全关闭了!");
                cover_leftblur.setVisibility(View.INVISIBLE);
            }
        };

到这里就实现了这个特殊的模糊效果,展示一下实现的效果图:

 

 

但是有个问题还未解决,处理时机是什么?

我觉得如果侧边栏要求不能侧滑出来的话,无疑放在张开侧边栏按钮的点击回调了最恰当,原因有二:其一,主背景更新频繁,暂停播放的时候会有播放控制按钮出现,这些也应该出现在模糊区域,点击就处理,处理的结果是最新的,无论播放状态是什么,不会出现模糊区域显示不同步的情况(进度条除外);其二,主背景渲染完成的监听无疑是不行的,界面更新太频繁了,底部的进度条一直在跑,监听的回调一直在触发,cpu占用率过高是个很大的问题;现在要求,侧边栏能侧滑出来,于是考虑侧边栏有没有开始展开的监听,如果每次开始展开,我就处理一次,无疑是处理次数是最少的(主背景更改了,用户也可能不展开侧边栏).

这个处理时机的问题后续还要解决,先写到这,如果有什么好的建议,欢迎留言交流一下.

                             

 

 

 

 

posted @ 2017-05-28 10:39  你要  阅读(415)  评论(0编辑  收藏  举报