動態高斯模糊適配不同尺寸

介紹

不同UI大小尺寸不同需要在特定區域進行高斯模糊適配,例如system ui下拉高度不同背景高斯模糊不同,或彈框背景區域做高斯模糊處理。

 

原理

1.截取當前屏幕圖片(使用截圖接口)

2.根據當前UI計算位置,大小

3.在截圖bitmap上截取圖片

4.高斯模糊處理截取後的圖片

5.將圖片設置爲背景

 

具體實現

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

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

    private void setViewBlur(){
        if(TextUtils.isEmpty(ShotPath)){
            return;
        }
        File file = new File(ShotPath);
        if(!file.exists()){
            Log.d(TAG,"setViewBlur file not exist shotPath = "+ShotPath);
            return;
        }
        if(getHandler() != null){
            getHandler().removeCallbacks(blurRunnable);
            getHandler().postDelayed(blurRunnable,10);
        }
    }

    Runnable blurRunnable = new Runnable() {
        @Override
        public void run() {
            blurBimtap(ScreenShotUtil.cropShotBitmap(ShotPath,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 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;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章