1. 程式人生 > >Android 仿PC端QQ自由截圖,可支援一次截多個區域

Android 仿PC端QQ自由截圖,可支援一次截多個區域

仿PC端QQ截圖,可任意截圖,這裡只做了矩形這一種形狀,可同時支援擷取多個區域,支援撤銷上次截圖,重新擷取。
這裡寫圖片描述

實現原理:
自定義SurfaceView,在SurfaceView上繪製具有一個可拉伸,移動的矩形框,當點選截圖按鈕後,計算矩形框的座標值及原圖尺寸,通過比例將矩形框的座標值轉化到原圖中相對應的座標,然後進行裁剪。

這裡矩形框目前只設置了兩個。

**

**

實現程式碼:

public class CustomSurfaceView extends SurfaceView implements
        SurfaceHolder.Callback
, Runnable, Handler.Callback {
// SurfaceHolder private SurfaceHolder mSurfaceHolder; /** * 螢幕尺寸 */ private int viewWidth; private int viewHeight; // 線寬 private int StrokeWidth = 5; private boolean startDraw; //半徑 private int radius; // Path private
Path mPath = new Path(); // 畫筆 private Paint mpaint = new Paint(); private Canvas canvas; //滑板背景(儲存繪製的圖片) private Bitmap saveBitmap; //影象 Bitmap bitmap; // 圖片路徑 private String urlPath; private List<DrawPath> drawPathList = new ArrayList<>(); /** * X 、 Y 方向的圖片和螢幕比例 */
private float scaleX, scaleY; /** * 0矩形 * 1撤回 */ private static int state = 0; public void setState(int state) { this.state = state; } public CustomSurfaceView(Context context, String url, boolean s) { this(context, null); this.urlPath = url; saveBitmap = Bitmap.createBitmap(720, 1000, Bitmap.Config.ARGB_8888); } public CustomSurfaceView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); // 初始化 } private void initView() { setMeasuredDimension(720, 1000); mSurfaceHolder = getHolder(); mSurfaceHolder.addCallback(this); mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT); setFocusable(true); setFocusableInTouchMode(true); this.setKeepScreenOn(true); } private Handler handler = new Handler(this); @Override public void run() { while (startDraw) { if (urlPath != null) { try { bitmap = BitmapUtils.toBitmap(urlPath, getWidth(), getHeight()); if (bitmap == null) { startDraw = true; } else { startDraw = false; } } catch (Exception e) { Log.d("CustomSurfaceView", "CustomSurfaceView ------- " + e.toString()); } } handler.sendEmptyMessage(1); } } /* * 建立 */ @Override public void surfaceCreated(SurfaceHolder holder) { startDraw = true; canvas = mSurfaceHolder.lockCanvas(); canvas.setBitmap(saveBitmap); mSurfaceHolder.unlockCanvasAndPost(canvas); new Thread(this).start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); viewWidth = getWidth(); viewHeight = getHeight(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /* * 銷燬 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { startDraw = false; } int startX; int startY; int stopX; int stopY; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath = new Path(); mpaint = new Paint(); startX = 0; startY = 0; startX = (int) event.getX(); startY = (int) event.getY(); mPath.moveTo(startX, startY); break; case MotionEvent.ACTION_MOVE: stopX = (int) event.getX(); stopY = (int) event.getY(); if (state == 0) { draws(); } break; case MotionEvent.ACTION_UP: if (drawPathList.size() + 1 <= 1){ if (state == 0) { mPath.moveTo(startX, startY); mPath.lineTo(startX, stopY); mPath.lineTo(stopX, stopY); mPath.lineTo(stopX, startY); mPath.lineTo(startX, startY); mPath.close(); } } position.add(union((int) (stopX / scaleX), (int) (stopY / scaleY), (int) (startX / scaleX), (int) (startY / scaleY), (int) (startX / scaleX), (int) (startY / scaleY))); setPosition(position); drawPathList.add(new DrawPath(mpaint, mPath)); // 限制繪製矩形個數 if (drawPathList.size() == 3){ drawPathList.remove(drawPathList.size() - 2); // drawPathList.add(new DrawPath(mpaint, mPath)); } if (position.size() == 3){ position.remove(position.size() - 2); // position.add(union((int) (stopX / scaleX), (int) (stopY / scaleY), // (int) (startX / scaleX), (int) (startY / scaleY), // (int) (startX / scaleX), (int) (startY / scaleY))); setPosition(position); } break; } return true; } /** * 判斷四個頂點的位置,繪製矩形 * @param x * @param y * @param left * @param top * @param right * @param bottom * @return */ public Postion union(int x, int y, int left, int top, int right, int bottom) { int temp = 0; if (x < left) { temp = left; left = x; right = temp; } else if (x > right) { temp = right; right = x; left = temp; } if (y < top) { temp = top; top = y; bottom = temp; } else if (y > bottom) { temp = bottom; bottom = y; top = temp; } return new Postion(left, top, right, bottom); } /** * 獲取繪製的四個點在原圖的位置集合 */ private List<Postion> position = new ArrayList<>(); public List<Postion> getPosition() { return position; } public void setPosition(List<Postion> position1) { this.position = position1; } public void draws() { if (bitmap == null) { Toast.makeText(getContext(), "載入圖片失敗", Toast.LENGTH_SHORT).show(); Log.e("msg", "載入圖片失敗"); return; } canvas = mSurfaceHolder.lockCanvas(); Rect rectF = new Rect(0, 0, getWidth(), getHeight()); //w和h分別是螢幕的寬和高,也就是你想讓圖片顯示的寬和高 scaleX = (float) getWidth() / bitmap.getWidth(); scaleY = (float) getHeight() / bitmap.getHeight(); canvas.drawBitmap(bitmap, null, rectF, null); mpaint.setStyle(Paint.Style.STROKE); mpaint.setAntiAlias(true); for (int i = 0; i < drawPathList.size(); i++) { //把path中的路線繪製出來 canvas.drawPath(drawPathList.get(i).path, drawPathList.get(i).paint); } mpaint.setColor(Color.RED); if (state == 0) { mpaint.setColor(Color.RED); mpaint.setStyle(Paint.Style.STROKE); mpaint.setStrokeWidth(StrokeWidth); canvas.drawRect(startX, startY, stopX, stopY, mpaint); } mSurfaceHolder.unlockCanvasAndPost(canvas); } @Override public boolean handleMessage(Message msg) { canvas = mSurfaceHolder.lockCanvas(); //這裡相當於是一個預覽圖 Rect rectF = new Rect(0, 0, viewWidth, viewHeight); //w和h分別是螢幕的寬和高,也就是你想讓圖片顯示的寬和高 if (bitmap!= null&& canvas!= null) canvas.drawBitmap(bitmap, null, rectF, null); if (canvas!= null) mSurfaceHolder.unlockCanvasAndPost(canvas); if (bitmap != null) { startDraw = false; } return false; } public class DrawPath { public Paint paint; public Path path; public DrawPath(Paint paint, Path path) { this.paint = paint; this.path = path; } } /** * 撤銷上一個矩形 */ public void revocation() { if (drawPathList.size() > 0) { drawPathList.remove(drawPathList.size() - 1); position.remove(position.size() - 1); if (drawPathList.size() == 0){ position = new ArrayList<>(); } startX = 0; startY = 0; stopX = 0; stopY = 0; draws(); } } /** * 位置 Bean */ public class Postion{ public int left; public int top; public int right; public int bottom; public int getLeft() { return left; } public int getTop() { return top; } public int getRight() { return right; } public int getBottom() { return bottom; } public Postion(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } } }

在Activity中對CustomSurfaceView進行例項化,並傳入圖片,監聽按鈕進行裁剪和撤銷處理

    surfce = new CustomSurfaceView(CropActivity.this, photoPath, false);
    linear.addView(surfce);

    //設定當前狀態為畫矩形
    surfce.setState(0);

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            position = new ArrayList<>();
            if (bitmap != null) {
                position = surfce.getPosition();

                bitmap1 = null;
                bitmap2 = null;
                bitmap1 = Bitmap.createBitmap(bitmap, surfce.getPosition().get(0).getLeft(),
                        surfce.getPosition().get(0).getTop(),
                        surfce.getPosition().get(0).getRight() - surfce.getPosition().get(0).getLeft(),
                        surfce.getPosition().get(0).getBottom() - surfce.getPosition().get(0).getTop());
                bitmap2 = Bitmap.createBitmap(bitmap, surfce.getPosition().get(1).getLeft(),
                        surfce.getPosition().get(1).getTop(),
                        surfce.getPosition().get(1).getRight() - surfce.getPosition().get(1).getLeft(),
                        surfce.getPosition().get(1).getBottom() - surfce.getPosition().get(1).getTop());
                if (bitmap == null || bitmap1 == null || bitmap2 == null || position.size() != 2) {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(CropActivity.this);
                    builder.setMessage("照片裁剪失敗,請重新裁剪!!")
                            .setTitle("提示")
                            .setPositiveButton("返回", null);
                } else {
                    image01.setImageBitmap(bitmap1);
                    image02.setImageBitmap(bitmap2);
                }
            }
        }
    });

    findViewById(R.id.canle).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            surfce.revocation();
        }
    });