zoukankan      html  css  js  c++  java
  • 侧边栏高斯模糊(二)

    • 闲言碎语

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

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

     

    • 分析思路

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

    后面的主背景会改变(先忽略播放条的滚动),每次展开抽屉时看到的模糊图层视图基本不一样,这就要求能动态获取主背景的快照 -->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占用率过高是个很大的问题;现在要求,侧边栏能侧滑出来,于是考虑侧边栏有没有开始展开的监听,如果每次开始展开,我就处理一次,无疑是处理次数是最少的(主背景更改了,用户也可能不展开侧边栏).

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

                                 

     

     

     

  • 相关阅读:
    input 特殊字符限制
    angular $http服务
    angular $resouse服务
    ng-model-options 时延
    Pytorch之数据处理
    python 小顶堆
    刷题套路总结
    数组分成和尽可能相等的子数组
    python3.7 sorted 自定义排序
    Leetcode 二维数组周游 54
  • 原文地址:https://www.cnblogs.com/fuyaozhishang/p/6914619.html
Copyright © 2011-2022 走看看