Android10 SystemUI下拉栏背景高斯模糊

Android10 SystemUI下拉栏背景高斯模糊

 

原理

1.截取当前屏幕图片(使用截图接口)

2.根据当前UI计算位置,大小

3.在截图bitmap上截取图片

4.高斯模糊处理截取后的图片

5.将图片设置为背景

6.把systemui默认背景透明

 

具体实现

1.截取当前屏幕图片(使用截图接口)

public static String screenShotByShell(Context context){
        // 获取内置当前应用路径
        String sdCardPath = context.getCacheDir().getAbsolutePath()+screenShotPath;
        File dir = new File(sdCardPath);
        if(!dir.exists()){
            dir.mkdirs();
        }else{
            delteDirectoryFiles(sdCardPath);
        }
        // 图片文件路径
        String filePath = sdCardPath + File.separator +"screenshot-"+System.currentTimeMillis()+".png";
        String shotCmd = "screencap -p " + filePath + " \n";
        try {
            Runtime.getRuntime().exec(shotCmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath;
    }

2.计算位置剪切图片

public static Bitmap cropShotBitmap(String path,View view){
        int outWidth = view.getWidth();
        int outHeight = view.getHeight();
        int[] result = new int[2];
        view.getLocationOnScreen(result);
        int x = result[0];
        int y = result[1];
        Bitmap bitmap = ScreenShotUtil.cropBitmap(path,outWidth,outHeight,x,y);
        Log.d(TAG,"screenShotByShell path = "+path+" x = "+x+" y = "+y+" outWidth = "+outWidth+" outHeight = "+outHeight);
        return bitmap;
    }
 
public static Bitmap cropBitmap(String screenShotPath,int outWidth, int outHeight, int x, int y){
        Bitmap bitmap = BitmapFactory.decodeFile(screenShotPath);
        if(bitmap != null){
            //从屏幕整张图片中截取指定区域
            try {
                if(outHeight > bitmap.getHeight()){
                    outHeight = bitmap.getHeight();
                }
                if(outWidth > bitmap.getWidth()){
                    outWidth = bitmap.getWidth();
                }
                if(x < 0){
                    x = 0;
                }
                if(y < 0){
                    y = 0;
                }
                bitmap = Bitmap.createBitmap(bitmap, x, y, outWidth, outHeight);
                //File file = new File(screenShotPath);
                //file.delete();
               // String path = screenShotPath.replace(".png",System.currentTimeMillis()+".png");
                //onSaveBitmap(bitmap,screenShotPath);
                return bitmap;
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
        if(bitmap != null){
            Log.d(TAG,"cropBitmap sucess");
        }else{
            Log.d(TAG,"cropBitmap fail");
        }
        return null;
    }

3.高斯模糊处理

/**
     * 使用RenderScript实现高斯模糊的算法
     * @param bitmap
     * @return
     */
    public static Bitmap blur(Context context,Bitmap bitmap,int radius){
        //Let's create an empty bitmap with the same size of the bitmap we want to blur
        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        //Instantiate a new Renderscript
        RenderScript rs = RenderScript.create(context);
        //Create an Intrinsic Blur Script using the Renderscript
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        //Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
        Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
        Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
        //Set the radius of the blur: 0 < radius <= 25
        blurScript.setRadius(radius);
        //Perform the Renderscript
        blurScript.setInput(allIn);
        blurScript.forEach(allOut);
        //Copy the final bitmap created by the out Allocation to the outBitmap
        allOut.copyTo(outBitmap);
        //recycle the original bitmap
        bitmap.recycle();
        //After finishing everything, we destroy the Renderscript.
        rs.destroy();
 
        return outBitmap;
 
    }

完整代码

1.自定义高斯模糊View

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
 
import com.royole.sidesplitscreen.R;
import com.royole.sidesplitscreen.utils.BlurUtil;
import com.royole.sidesplitscreen.utils.ImageUtils;
import com.royole.sidesplitscreen.utils.ScreenShotUtil;
 
import java.io.File;
 
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
 
public class BlurBackgoundView extends View {
 
    private final String TAG = getClass().getSimpleName();
    private final int DURATION = 300;
    private Paint paint = new Paint();
    private Paint prePaint = new Paint();
    private int currentRadius = 32;
    protected BitmapShader mBitmapShader;
    protected BitmapShader preBitmapShader;
    private ValueAnimator mValueAnimator;
 
    private String ShotPath;
    public BlurBackgoundView(Context context) {
        this(context,null);
    }
 
    public BlurBackgoundView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,-1);
    }
 
    public BlurBackgoundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr,-1);
    }
 
    public void setCurrentRadius(int currentRadius) {
        this.currentRadius = currentRadius;
    }
 
    public BlurBackgoundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
 
    private void init() {
        currentRadius = (int) getContext().getResources().getDimension(R.dimen.recycle_radius);
        initPaint(paint);
        initPaint(prePaint);
    }
 
    private void initPaint(Paint paint){
        paint.setColor(getContext().getColor(R.color.blur_background_color));
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2);
    }
 
    public void setShotPath(String shotPath) {
        ShotPath = shotPath;
        setViewBlur();
    }
 public void setShotBitmap() {

        ShotBitmap = getShotBitmap();
        setViewBlurWithBitmap();
    }
    public void setShotBitmap(Bitmap bitmap) {
        ShotBitmap = bitmap;
        setViewBlurWithBitmap();
    }
/***
调用系统截屏
 Bitmap mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
*/
    private Bitmap getShotBitmap(){
        WindowManager mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

        Display mDisplay = mWindowManager.getDefaultDisplay();
        DisplayMetrics mDisplayMetrics = new DisplayMetrics();
        mDisplay.getRealMetrics(mDisplayMetrics);
        Rect crop = new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
        int rot = mDisplay.getRotation();
        int width = crop.width();
        int height = crop.height();
        Bitmap mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
        mScreenBitmap.setHasAlpha(false);
        mScreenBitmap.prepareToDraw();
        return mScreenBitmap;

    }
 
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        setViewBlur();
    }
 
     private void setViewBlurWithBitmap(){

        if(ShotBitmap == null){
            Log.d(TAG,"setViewBlur bitmap is null  ");
            return;
        }
        if(getHandler() != null){
            getHandler().removeCallbacks(blurBitmapRunnable);
            getHandler().postDelayed(blurBitmapRunnable,10);
        }
    }

    Runnable blurRunnable = new Runnable() {
        @Override
        public void run() {
            blurBimtap(ScreenShotUtil.cropShotBitmap(ShotPath, BlurBackgoundView.this));
        }
    };
    Runnable blurBitmapRunnable = new Runnable() {
        @Override
        public void run() {
            blurBimtap(ScreenShotUtil.cropShotBitmap(ShotBitmap, BlurBackgoundView.this));
        }
    };
 
    private void blurBimtap(Bitmap bitmap){
        BlurUtil.getBlurBitmap(getContext(),bitmap, 24,new BlurUtil.BitmapBlurCallBack(){
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void finishHandleBitmap(Bitmap bitmap) {
                if(bitmap != null) {
                    Log.d(TAG,"finishHandleBitmap set bitmap.width = "+bitmap.getWidth()+" bitmap.height = "+bitmap.getHeight());
                    setBlurBitmap(bitmap);
                }
            }
        });
    }
 
    private void setBlurBitmap(Bitmap blurBitmap) {
        if(mBitmapShader != null){
            preBitmapShader = mBitmapShader;
            prePaint.setShader(preBitmapShader);
            prePaint.setFilterBitmap(true);
        }
        if (blurBitmap != null) {
            blurBitmap.prepareToDraw();
            mBitmapShader = new BitmapShader(blurBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            paint.setShader(mBitmapShader);
            paint.setFilterBitmap(true);
        }
        Log.d(TAG,"setBlurBitmap Width = "+getWidth()+" Height = "+getHeight()+" blurBitmap = "+blurBitmap);
        startAnimation();
    }
 
    private void startAnimation(){
        if(mValueAnimator != null && mValueAnimator.isRunning()){
            mValueAnimator.cancel();
        }
        mValueAnimator = ValueAnimator.ofFloat(0,255);
        mValueAnimator.setInterpolator(new AccelerateInterpolator());
        mValueAnimator.setDuration(DURATION);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float alpha = (float) animation.getAnimatedValue();
                paint.setAlpha((int) alpha);
                prePaint.setAlpha(Math.max(200-(int) alpha,0));
                invalidate();
            }
        });
        mValueAnimator.start();
    }
 
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.drawRoundRect(0, 0, getWidth(), getHeight(), currentRadius, currentRadius, prePaint);
        canvas.drawRoundRect(0, 0, getWidth(), getHeight(), currentRadius, currentRadius, paint);
    }
}

2.高斯模糊工具

import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
 
public class BlurUtil {
 
    public interface BitmapBlurCallBack {
        void finishHandleBitmap(Bitmap bitmap);
    }
 
    public static void getBlurBitmap(Context context,Bitmap bitmap,int radius, BitmapBlurCallBack bitmapBlurCallBack){
        android.os.Handler handler = new android.os.Handler();
        if(bitmap == null){
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap tempBitmap = blur(context,bitmap,radius);
                final Bitmap blurBitmap = blur(context,tempBitmap,radius);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(bitmapBlurCallBack != null){
                            bitmapBlurCallBack.finishHandleBitmap(blurBitmap);
                        }
                    }
                },0);
            }
        }).start();
    }
 
    /**
     * 使用RenderScript实现高斯模糊的算法
     * @param bitmap
     * @return
     */
    public static Bitmap blur(Context context,Bitmap bitmap,int radius){
        //Let's create an empty bitmap with the same size of the bitmap we want to blur
        Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        //Instantiate a new Renderscript
        RenderScript rs = RenderScript.create(context);
        //Create an Intrinsic Blur Script using the Renderscript
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        //Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
        Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
        Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
        //Set the radius of the blur: 0 < radius <= 25
        blurScript.setRadius(radius);
        //Perform the Renderscript
        blurScript.setInput(allIn);
        blurScript.forEach(allOut);
        //Copy the final bitmap created by the out Allocation to the outBitmap
        allOut.copyTo(outBitmap);
        //recycle the original bitmap
        bitmap.recycle();
        //After finishing everything, we destroy the Renderscript.
        rs.destroy();
 
        return outBitmap;
 
    }
}

3.截图工具

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.os.Environment;
import android.util.Log;
import android.view.View;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class ScreenShotUtil {
    private final static String TAG = "ScreenShotUtil";

    private static final String screenShotPath = File.separator +"screenshort";

    public static Bitmap cropShotBitmap(String path,View view){
        int outWidth = view.getWidth();
        int outHeight = view.getHeight();
        int[] result = new int[2];
        view.getLocationOnScreen(result);
        int x = result[0];
        int y = result[1];
        Bitmap bitmap = ScreenShotUtil.cropBitmap(path,outWidth,outHeight,x,y);
        Log.d(TAG,"screenShotByShell path = "+path+" x = "+x+" y = "+y+" outWidth = "+outWidth+" outHeight = "+outHeight);
        return bitmap;
    }

    public static Bitmap cropShotBitmap(Bitmap bitmapIn,View view){
        android.util.Log.w(TAG, "cropShotBitmap:getConfig = "+ bitmapIn.getConfig() );
        bitmapIn = convertHardWareBitmap(bitmapIn);
        android.util.Log.w(TAG, "cropShotBitmap:222getConfig = "+ bitmapIn.getConfig() );
        int outWidth = view.getWidth();
        int outHeight = view.getHeight();
        int[] result = new int[2];
        view.getLocationOnScreen(result);
        int x = result[0];
        int y = result[1];
        Bitmap bitmap = ScreenShotUtil.cropBitmap(bitmapIn,outWidth,outHeight,x,y);
        Log.d(TAG,"screenShotByShell  x = "+x+" y = "+y+" outWidth = "+outWidth+" outHeight = "+outHeight);
        return bitmap;
    }


    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);
    }

    public static String screenShotByShell(Context context){
        // 获取内置SD卡路径
        String sdCardPath = context.getCacheDir().getAbsolutePath()+screenShotPath;
        File dir = new File(sdCardPath);
        if(!dir.exists()){
            dir.mkdirs();
        }else{
            delteDirectoryFiles(sdCardPath);
        }
        // 图片文件路径
        String filePath = sdCardPath + File.separator +"screenshot-"+System.currentTimeMillis()+".png";
        String shotCmd = "screencap -p " + filePath + " \n";
        try {
            Runtime.getRuntime().exec(shotCmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath;
    }

    private static boolean delteDirectoryFiles(String path){
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }
        if (file.isFile()) {
            file.delete();
            return true;
        }
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            return false;
        }
        for (File f : files) {
            if (f.isDirectory()) {
            } else {
                f.delete();
            }
        }
        return true;
    }

    public static Bitmap cropBitmap(String screenShotPath,int outWidth, int outHeight, int x, int y){
        Bitmap bitmap = BitmapFactory.decodeFile(screenShotPath);
        if(bitmap != null){
            //从屏幕整张图片中截取指定区域
            try {
                if(outHeight > bitmap.getHeight()){
                    outHeight = bitmap.getHeight();
                }
                if(outWidth > bitmap.getWidth()){
                    outWidth = bitmap.getWidth();
                }
                if(x < 0){
                    x = 0;
                }
                if(y < 0){
                    y = 0;
                }
                bitmap = Bitmap.createBitmap(bitmap, x, y, outWidth, outHeight);
                //File file = new File(screenShotPath);
                //file.delete();
                // String path = screenShotPath.replace(".png",System.currentTimeMillis()+".png");
                //onSaveBitmap(bitmap,screenShotPath);
                return bitmap;
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
        if(bitmap != null){
            Log.d(TAG,"cropBitmap sucess");
        }else{
            Log.d(TAG,"cropBitmap fail");
        }
        return null;
    }
    public static Bitmap cropBitmap(Bitmap bitmap,int outWidth, int outHeight, int x, int y){
        //Bitmap bitmap = BitmapFactory.decodeFile(screenShotPath);
        if(bitmap != null){
            //从屏幕整张图片中截取指定区域
            try {
                if(outHeight > bitmap.getHeight()){
                    outHeight = bitmap.getHeight();
                }
                if(outWidth > bitmap.getWidth()){
                    outWidth = bitmap.getWidth();
                }
                if(x < 0){
                    x = 0;
                }
                if(y < 0){
                    y = 0;
                }
                bitmap = Bitmap.createBitmap(bitmap, x, y, outWidth, outHeight);
                //File file = new File(screenShotPath);
                //file.delete();
                // String path = screenShotPath.replace(".png",System.currentTimeMillis()+".png");
                //onSaveBitmap(bitmap,screenShotPath);
                return bitmap;
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
        if(bitmap != null){
            Log.d(TAG,"cropBitmap sucess");
        }else{
            Log.d(TAG,"cropBitmap fail");
        }
        return null;
    }
}

6.把systemui默认背景透明
修改文件:
/frameworks/base /packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java

参考文章:
动态高斯模糊适配不同尺寸
Android8.1 SystemUI 下拉通知栏添加高斯模糊
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android中,如果想要自定义下拉通知的颜色,可以通过修改SystemUI的相关设置来实现。 首先,为了修改SystemUI的颜色,需要获取相应的权限。我们可以在AndroidManifest.xml文件中添加如下代码: ```xml <uses-permission android:name="android.permission.STATUS_BAR"/> ``` 接下来,在我们的项目中创建一个名为values的文件夹,并在其中创建一个名为colors.xml的文件。在这个文件中,我们可以定义我们想要使用的颜色。例如,我们可以定义一个名为notification_background的颜色,用于设置下拉通知背景颜色。代码如下: ```xml <resources> <color name="notification_background">#FF0000</color> </resources> ``` 然后,我们需要修改SystemUI的源代码,以更新背景颜色。具体来说,我们需要找到StatusBar类中的updateResources方法,并在该方法中添加以下代码: ```java Context context = mContext.createPackageContext("com.example.notificationtest", Context.CONTEXT_IGNORE_SECURITY); // 替换为自己的包名 int color = context.getResources().getColor(R.color.notification_background); mBackgroundView.setBackgroundColor(color); ``` 最后,我们需要重新编译并安装我们的应用程序。一旦安装完成,我们就可以看到下拉通知背景颜色已经根据我们在colors.xml中定义的颜色进行了自定义。 以上是通过修改SystemUI的方式来自定义下拉通知的颜色。请注意,这种方式需要具备系统级权限,因此只适用于特定的Android设备。在实际开发中,请确保在使用这种方式之前了解并遵守相关的法规和政策,以避免违规行为。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值