由于项目需要,实现一个类似于华为杂志锁屏上滑模糊的效果,先说一下思路:
- 自定义一个类似抽屉拖拽效果从手机底部滑进的view,支持手势滑动,并提供上下滑动变化监听;
- 在上下滑动变化的监听方法,截屏:截取自定义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!
网友评论