需求介绍:在状态栏下拉时,截取原先屏幕,并绘制成高斯模糊然后设置为背景。
首先,找到状态栏下拉的控制类NotificationPanelViewController.java,然后找个类里面有个核心的方法:
private void setBlurBackground() {
Bitmap bitmap = ScreenShotUtil.takeScreenShot(mView.getContext());
if (bitmap == null) {
Log.d(TAG, "setBlurBackground bitmap == null");
return;
}
Bitmap cutBitmap = ScreenShotUtil.convertHardWareBitmap(bitmap);
Bitmap blurBitmap = BlurUtil.blur(mView.getContext(), cutBitmap,
BlurUtil.BLUR_RADIUS_MAX);
BitmapUtils.recycleImageView(mBlurView);
//mBlurView.setVisibility(View.VISIBLE);
//mBlurView.setImageBitmap(blurBitmap);
//mBlurView.setAlpha(0.85f);
nBlurView.invalidate();
mBlurView.setVisibility(View.VISIBLE);
nBlurView.setVisibility(View.VISIBLE);
mBlurView.setImageBitmap(blurBitmap);
mBlurView.setAlpha(0.85f);
nBlurView.setBlurredView(mBlurView);
}
这里使用到了工具类ScreenShotUtil.java,下面就是工具类的具体代码展示:
public static Bitmap takeScreenShot(Context context) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getRealMetrics(displayMetrics);
final float[] dims = {displayMetrics.widthPixels, displayMetrics.heightPixels};
Rect crop = new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
int rot = display.getRotation();
int width = crop.width();
int height = crop.height();
return captureScreenshot(crop, display);
}
private static Bitmap captureScreenshot(Rect crop,Display display) {
int width = crop.width();
int height = crop.height();
Bitmap screenshot = null;
final DisplayAddress address = display.getAddress();
if (address instanceof DisplayAddress.Physical) {
final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) address;
final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(
physicalAddress.getPhysicalDisplayId());
// 捕获参数
final SurfaceControl.DisplayCaptureArgs captureArgs =
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
.setSourceCrop(crop)
.setSize(width, height)
.build();
// 屏幕截图硬件缓存
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
SurfaceControl.captureDisplay(captureArgs);
// 截图缓存
screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
}
return screenshot;
}
@RequiresApi(api = Build.VERSION_CODES.O)
public static Bitmap convertHardWareBitmap(Bitmap src) {
if (src.getConfig() != Bitmap.Config.HARDWARE) {
//return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
return src;
}
final int w = src.getWidth();
final int h = src.getHeight();
// For hardware bitmaps, use the Picture API to directly create a software bitmap
Picture picture = new Picture();
Canvas canvas = picture.beginRecording(w, h);
canvas.drawBitmap(src, 0, 0, null);
picture.endRecording();
return Bitmap.createBitmap(picture, w, h, Bitmap.Config.ARGB_8888);
}
}
总之通过这个工具类的一系列操作可以获取一张屏幕截图,然后setBlurBackground()方法将这张截图变成了高斯模糊并设置到当前背景。
举一个调用的地方为例:
if (mKeyguardShowing && mQsVisible != qsVisible) {
if(qsVisible){
setBlurBackground();
} else {
nBlurView.invalidate();
mBlurView.setVisibility(View.GONE);
BitmapUtils.recycleImageView(mBlurView);
nBlurView.setVisibility(View.GONE);
}
}
mQsVisible是之前存的状态栏状态,打开为true关闭是false,而qsViseble是现在的状态,mKeyguradShowing是判断锁屏状态,也就是锁屏时并且状态栏状态发生变化(从没显示到显示或者从显示到没显示)时就执行下面的代码,如果现在状态栏是打开状态,就设置高斯模糊,否则就关闭高斯模糊背景