feat: 添加拖动时毛玻璃效果

This commit is contained in:
xiaoyan159@6800H 2024-10-18 13:39:10 +08:00
parent bd3e498888
commit 27c918f1be
2 changed files with 234 additions and 41 deletions

View File

@ -72,6 +72,9 @@ public class SplitLayout extends ViewGroup {
private View switchLongPressChildView = null; // 记录用户长按拖动的子View
private boolean hasSwitchChild = false; // 子View是否通过手势切换完成
private long LONG_PRESS_TIME = 1200;
private Bitmap blurBitmap; // 毛玻璃效果的Bitmap
private Paint splitBgPaint = new Paint(); // 用于绘制分割线背景的画笔
private Paint splitPressBgPaint = new Paint(); // 用于绘制分割线背景的画笔
// private Vibrator vibrator;
public SplitLayout(Context context) {
@ -93,8 +96,8 @@ public class SplitLayout extends ViewGroup {
mHandleDrawable = a.getDrawable(R.styleable.SplitLayout_splitHandleDrawable);
if (mHandleDrawable == null) {
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(0x990288d1));
stateListDrawable.addState(new int[] {}, new ColorDrawable(Color.TRANSPARENT));
stateListDrawable.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(getResources().getColor(R.color.draw_progress_bg_color)));
stateListDrawable.addState(new int[] {}, new ColorDrawable(getResources().getColor(R.color.material_pink_500)));
stateListDrawable.setEnterFadeDuration(150);
stateListDrawable.setExitFadeDuration(150);
mHandleDrawable = stateListDrawable;
@ -117,6 +120,8 @@ public class SplitLayout extends ViewGroup {
a.recycle();
mPaint.setColor(dragForgroundColor);
splitBgPaint.setColor(getResources().getColor(R.color.material_pink_500));
splitPressBgPaint.setColor(getResources().getColor(R.color.material_lightblue_500));
// // 获取震动权限
// vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
// vibrator.vibrate(VibrationEffect.createOneShot(500, 125));
@ -211,7 +216,11 @@ public class SplitLayout extends ViewGroup {
mHandleDrawable.setState(PRESSED_STATE_SET);
mIsDragging = true;
getParent().requestDisallowInterceptTouchEvent(true);
getBitmapFromChildView(); // 截屏当前两个子View的图片用于在拖动过程中的
// getBitmapFromChildView(); // 截屏当前两个子View的图片用于在拖动过程中的
blurBitmap = getBlurBitmap();
// 开始绘制蒙版图层
cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR);
cachedCanvas.drawBitmap(blurBitmap, 0, 0, null);
invalidate();
} else {
mIsDragging = false;
@ -362,6 +371,45 @@ public class SplitLayout extends ViewGroup {
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
Log.d("SplitLayout", "dispatchDraw");
if (mIsDragging) { // 开始拖动
// // 获取两个子View的截图Bitmap
// cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR);
// if (cachedBitmapArray != null) {
// Rect child0Rect = new Rect();
// Rect child1Rect = new Rect();
// if (mOrientation == VERTICAL) {
// child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2));
// child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight());
// } else {
// child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight());
// child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight());
// }
// if (splitIsShowSnapshotView) {
// cachedCanvas.drawBitmap(cachedBitmapArray[0], null, child0Rect, null);
// }
// cachedCanvas.drawRect(child0Rect, mPaint);
//// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(),
//// child0Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2),
//// child0Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null);
// if (splitIsShowSnapshotView) {
// cachedCanvas.drawBitmap(cachedBitmapArray[1], null, child1Rect, null);
// }
// cachedCanvas.drawRect(child1Rect, mPaint);
//// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(),
//// child1Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2),
//// child1Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null);
// canvas.drawBitmap(cachedBitmap, 0, 0, null);
// }
canvas.drawBitmap(cachedBitmap, 0, 0, null);
} else if (mIsSwitching) { // 开始拖动切换
if (hasSwitchChild) {
resetChildSnapshotBitmap(canvas, true);
} else {
resetChildSnapshotBitmap(canvas, false);
}
}
if (mSplitPosition != INVAID_SPLITPOSITION && mHandleDrawable != null) {
final int splitPosition = Math.round(mSplitPosition);
if (mOrientation == VERTICAL) {
@ -369,46 +417,12 @@ public class SplitLayout extends ViewGroup {
} else {
mHandleDrawable.setBounds(splitPosition - mHandleSize / 2, 0, splitPosition + mHandleSize / 2, mHeight);
}
mHandleDrawable.draw(canvas);
}
Log.d("SplitLayout", "dispatchDraw");
if (mIsDragging) { // 开始拖动
// 获取两个子View的截图Bitmap
cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR);
if (cachedBitmapArray != null) {
Rect child0Rect = new Rect();
Rect child1Rect = new Rect();
if (mOrientation == VERTICAL) {
child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2));
child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight());
} else {
child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight());
child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight());
}
if (splitIsShowSnapshotView) {
cachedCanvas.drawBitmap(cachedBitmapArray[0], null, child0Rect, null);
}
cachedCanvas.drawRect(child0Rect, mPaint);
// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(),
// child0Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2),
// child0Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null);
if (splitIsShowSnapshotView) {
cachedCanvas.drawBitmap(cachedBitmapArray[1], null, child1Rect, null);
}
cachedCanvas.drawRect(child1Rect, mPaint);
// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(),
// child1Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2),
// child1Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null);
canvas.drawBitmap(cachedBitmap, 0, 0, null);
}
} else if (mIsSwitching) { // 开始拖动切换
if (hasSwitchChild) {
resetChildSnapshotBitmap(canvas, true);
if (mIsDragging) {
canvas.drawRect(mHandleDrawable.getBounds(),splitPressBgPaint);
} else {
resetChildSnapshotBitmap(canvas, false);
canvas.drawRect(mHandleDrawable.getBounds(),splitBgPaint);
}
mHandleDrawable.draw(canvas);
}
}
@ -493,6 +507,13 @@ public class SplitLayout extends ViewGroup {
}
}
// 获取高斯模糊的bitmap图片
private Bitmap getBlurBitmap() {
// 先获取当前界面的整体截图
Bitmap currentBitmap = loadBitmapFromViewBySystem(this);
return UtilBitmap.blurBitmap(getContext(), currentBitmap, 20f);
}
/**
*此方法直接截取屏幕指定view区域的内容
* @param view 需要截取屏幕的图片view

View File

@ -0,0 +1,172 @@
package com.mixiaoxiao.library.splitlayout;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.Log;
import android.widget.ImageView;
/**
* 图片工具类
* <p>
* Created by Bamboy on 2017/04/01.
*/
public class UtilBitmap {
/**
* 图片缩放比例
*/
private static final float BITMAP_SCALE = 1f;
/**
* 将Drawable对象转化为Bitmap对象
*
* @param drawable Drawable对象
* @return 对应的Bitmap对象
*/
private static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap;
//如果本身就是BitmapDrawable类型 直接转换即可
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
//取得Drawable固有宽高
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
//创建一个1x1像素的单位色图
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
} else {
//直接设置一下宽高和ARGB
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
//重新绘制Bitmap
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* 模糊ImageView
*
* @param context
* @param img ImageView
* @param level 模糊等级0 ~ 25之间
*/
public static void blurImageView(Context context, ImageView img, float level) {
// 将图片处理成模糊
Bitmap bitmap = blurBitmap(context, drawableToBitmap(img.getDrawable()), level);
if (bitmap != null) {
img.setImageBitmap(bitmap);
}
}
/**
* 模糊ImageView
*
* @param context
* @param img ImageView
* @param level 模糊等级0 ~ 25之间
* @param color 为ImageView蒙上一层颜色
*/
public static void blurImageView(Context context, ImageView img, float level, int color) {
// 将图片处理成模糊
Bitmap bitmap = blurBitmap(context, drawableToBitmap(img.getDrawable()), level);
if (bitmap != null) {
Drawable drawable = coverColor(context, bitmap, color);
img.setScaleType(ImageView.ScaleType.FIT_XY);
img.setImageDrawable(drawable);
} else {
img.setImageBitmap(null);
img.setBackgroundColor(color);
}
}
/**
* 将bitmap转成蒙上颜色的Drawable
*
* @param context
* @param bitmap
* @param color 要蒙上的颜色
* @return Drawable
*/
public static Drawable coverColor(Context context, Bitmap bitmap, int color) {
Paint paint = new Paint();
paint.setColor(color);
RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
new Canvas(bitmap).drawRoundRect(rect, 0, 0, paint);
return new BitmapDrawable(context.getResources(), bitmap);
}
/**
* 模糊图片的具体方法
*
* @param context 上下文对象
* @param bitmap 需要模糊的图片
* @return 模糊处理后的图片
*/
public static Bitmap blurBitmap(Context context, Bitmap bitmap, float blurRadius) {
if (blurRadius < 0) {
blurRadius = 0;
}
if (blurRadius > 25) {
blurRadius = 25;
}
Bitmap outputBitmap = null;
try {
Class.forName("android.renderscript.ScriptIntrinsicBlur");
// 计算图片缩小后的长宽
int width = Math.round(bitmap.getWidth() * BITMAP_SCALE);
int height = Math.round(bitmap.getHeight() * BITMAP_SCALE);
if (width < 2 || height < 2) {
return null;
}
// 将缩小后的图片做为预渲染的图片
Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
// 创建一张渲染后的输出图片
outputBitmap = Bitmap.createBitmap(inputBitmap);
// 创建RenderScript内核对象
RenderScript rs = RenderScript.create(context);
// 创建一个模糊效果的RenderScript的工具对象
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
// 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间
// 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
// 设置渲染的模糊程度, 25f是最大模糊度
blurScript.setRadius(blurRadius);
// 设置blurScript对象的输入内存
blurScript.setInput(tmpIn);
// 将输出数据保存到输出内存中
blurScript.forEach(tmpOut);
// 将数据填充到Allocation中
tmpOut.copyTo(outputBitmap);
return outputBitmap;
} catch (Exception e) {
Log.e("Bemboy_Error", "Android版本过低");
return null;
}
}
}