模仿华为杂志锁屏上滑模糊效果实现

由于项目需要,实现一个类似于华为杂志锁屏上滑模糊的效果,先说一下思路:

  1. 自定义一个类似抽屉拖拽效果从手机底部滑进的view,支持手势滑动,并提供上下滑动变化监听;
  2. 在上下滑动变化的监听方法,截屏:截取自定义view下面的视图,进行模糊处理,然后作为view的背景。

下面说一下详细细节:
首先,从底部滑出的view在网上有很多,我这里用的是https://github.com/yingLanNull/ScrollLayout,我是直接下载源码,这样可以根据自己的需求进行修改:源码中,view的状态有三个:CLOSE、OPEN、EXIT,其中:

  • CLOSE是view滑到屏幕顶部时的状态;
  • OPEN是view显示时的状态;
  • EXIT时view隐藏或滑到屏幕底部时的状态;
    这里的view是继承的ScrollLayout:
int offset = (int) (ScreenUtil.getScreenHeight((Activity)context) * 0.5);
setMinOffset(0); //view滑到屏幕顶部时view下方视图的可见距离
setMaxOffset(offset); //打开状态时内容显示区域的高度
setExitOffset(0); //view退出时屏幕底部可见距离,0为不可见
setIsSupportExit(true); //是否支持下滑退出,支持会有下滑到最底部时的回调
setAllowHorizontalScroll(true);
setOnScrollChangedListener(mOnScrollChangedListener); //设置上下滑动监听
setToExit(); //默认令view置于屏幕底部

在上下滚动的监听中截取自定义view下面的视图,进行模糊处理,然后作为view的背景:

    private ScrollLayout.OnScrollChangedListener mOnScrollChangedListener = new ScrollLayout.OnScrollChangedListener(){
        @Override
        public void onScrollProgressChanged(float currentProgress) {
            NLog.i(TAG + ":onScrollProgressChanged currentProgress:"+currentProgress);
            if (currentProgress > -1) {
                float precent = 255;
                if(currentProgress>= 0) {
                    precent = 255 * currentProgress;
                    if (precent > 255) {
                        precent = 255;
                    } else if (precent < 0) {
                        precent = 0;
                    }
                }
                BlurBitmapUtil.blur(rootView, toBlurView, 14, 8); //截取自定义toBlurView下面的视图,进行模糊处理,然后作为toBlurView的背景
                if(getBackground()!= null) {
                    getBackground().setAlpha(255 - (int) precent);
                }
            }
        }

        @Override
        public void onScrollFinished(ScrollLayout.Status currentStatus) {
            if (currentStatus.equals(ScrollLayout.Status.EXIT)) {
            }
        }

        @Override
        public void onChildScroll(int top) {
        }
    };

blur的方法如下:

 /**
     * 设置高斯模糊
     *
     * @param fromView    从某个View获取截图
     * @param toView      高斯模糊设置到某个View上
     * @param radius      模糊度
     *                    取值在 0 - 25 之间,值越大,越模糊。
     * @param scaleFactor 缩放比例  一般设置为 8 即可,不需要特别注意。
     *                    设置这个属性,先进性缩放,再进行高斯模糊,效果会更好一点。
     */
    @SuppressWarnings("deprecation")
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public static void blur(View fromView, View toView, float radius,
                            float scaleFactor) {

        // 获取View的截图
//        fromView.buildDrawingCache();
//        Bitmap bkg = fromView.getDrawingCache();

        NLog.i(TAG + ":blur: bkg:"+bkg);
        //无需每次都截取,节约时间
        if(bkg == null){
            bkg = BitmapUtil.takeShotBy(fromView);
        }

        if (radius < 1 || radius > 26) {
            scaleFactor = 8;
            radius = 2;
        }

        Bitmap overlay = Bitmap.createBitmap(
                (int) (toView.getWidth() / scaleFactor),
                (int) (toView.getHeight() / scaleFactor),
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(overlay);


        int[] position = new int[2];
        toView.getLocationInWindow(position);
        int x = position[0];
        int y = position[1];

        NLog.i(TAG + ":blur: x:"+x+";y:"+y+";toView.getTop():"+toView.getTop());
        canvas.translate(-x / scaleFactor, -y
                / scaleFactor);
        canvas.scale(1 / scaleFactor, 1 / scaleFactor);
        Paint paint = new Paint();
        paint.setFlags(Paint.FILTER_BITMAP_FLAG);
        canvas.drawBitmap(bkg, 0, 0, paint);

        overlay = doBlur(overlay, (int) radius, true);//这个方法用的是FastBlur,自己百度就有
        toView.setBackground(new BitmapDrawable(overlay));
    }

基本就可以了,代码已上传至GitHub:https://github.com/ruoki/ScrollLayoutWithBlur.git,欢迎修正和star!

你可能感兴趣的:(模仿华为杂志锁屏上滑模糊效果实现)