美文网首页
Android 仿PC端QQ自由截图,可支持一次截多个区域

Android 仿PC端QQ自由截图,可支持一次截多个区域

作者: 延式主格 | 来源:发表于2018-07-27 15:55 被阅读0次

    仿PC端QQ截图,可任意截图,这里只做了矩形这一种形状,可同时支持截取多个区域,支持撤销上次截图,重新截取。

    实现原理:

    自定义SurfaceView,在SurfaceView上绘制具有一个可拉伸,移动的矩形框,当点击截图按钮后,计算矩形框的坐标值及原图尺寸,通过比例将矩形框的坐标值转化到原图中相对应的坐标,然后进行裁剪。

    项目源码:https://github.com/LeeVanie/CavansRect

    实现代码:

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

        }

        /**    * 判断四个顶点的位置,绘制矩形   

     * @paramx    

     * @paramy   

     * @paramleft   

     * @paramtop   

     * @paramright   

     * @parambottom    

     * @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 position = new ArrayList<>();

        public List getPosition() {

            return position;

        }

        public void setPosition(List 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 classDrawPath{        

    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 classPostion{        

    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();    //撤销

        }

        });

    相关文章

      网友评论

          本文标题:Android 仿PC端QQ自由截图,可支持一次截多个区域

          本文链接:https://www.haomeiwen.com/subject/uhdalxtx.html