surfaceview缩放裁剪图片

package com.sxwdsoft.recyclerviewapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.RelativeLayout;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class SurfaceActivity extends AppCompatActivity {

    private Bitmap bitmap;

    private SurfaceHolder holder;

    private boolean running = true;

    public static final int zoom = 1000;

    public static final int move = 1001;

    public int state = 0;

    private Rect srcRect, zoomRect;

    private int surfaceWidth, surfaceHeight;

    private int visibleScreenWidth, visibleScreenHieght;

    private MySurfaceView surfaceView;

    private int clipR = 200;

    private int[] clipXY;

    private int leftMax, rightMin, topMax, bottomMin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.b);
        running = true;
        surfaceView = new MySurfaceView(this);
        ViewGroup.LayoutParams surfaceParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

        RelativeLayout layout = new RelativeLayout(this);
        layout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        Button button = new Button(this);
        button.setText("截屏");
        layout.addView(surfaceView, surfaceParams);
        layout.addView(button, params);

        //截屏事件监听
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //停止缩放移动
                running = false;
                //获取锁定画布
                Canvas c = holder.lockCanvas();
                //获取画布尺寸
                int w = c.getWidth();
                int h = c.getHeight();
                //解锁画布
                holder.unlockCanvasAndPost(c);
                //创建一个和画布一样大小尺寸的无内容的bitmap对象
                Bitmap bit = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

                //绘制裁剪框
                Rect src = new Rect(w / 2 - clipR, h / 2 - clipR, w / 2 + clipR,
                        h / 2 + clipR);
                Rect dst = new Rect(0, 0,
                        clipR * 2, clipR * 2);
                RectF rectF = new RectF(dst);
                rectF.left = src.left;
                rectF.right = src.right;
                rectF.top = src.top;
                rectF.bottom = src.bottom;
                Canvas canvas = new Canvas(bit);
                canvas.drawColor(Color.TRANSPARENT);
                Paint p = new Paint();
                p.setAntiAlias(true);
                canvas.drawRoundRect(rectF, clipR, clipR, p);
                p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                //把画布上的冬衣全部绘制到bitmap上
                canvas.drawBitmap(bitmap, srcRect, zoomRect, p);

                //裁剪图片
                bit = Bitmap.createBitmap(bit, (int) rectF.left, (int) rectF.top, 2 * clipR, 2 * clipR);

                //保存图片
                File file = new File(getExternalCacheDir() + File.separator + "a.png");
                if (file.exists())
                    file.mkdir();
                FileOutputStream out = null;
                try {
                    out = new FileOutputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                bit.compress(Bitmap.CompressFormat.PNG, 100, out);
                if (out != null)
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        });
        setContentView(layout);
        Rect r = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
        visibleScreenWidth = r.width();
        visibleScreenHieght = r.height() - r.top;

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        View v = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
        visibleScreenHieght = visibleScreenHieght - v.getTop();
    }

    public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable, View.OnTouchListener {

        private float bitmapScale;

        private int bitmapWidth, bitmapHeight;

        public MySurfaceView(Context context) {
            super(context);
            init();
        }

        public MySurfaceView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }

        //初始化
        private void init() {
            holder = this.getHolder();
            holder.addCallback(this);
            this.setOnTouchListener(this);
            bitmapScale = ((float) bitmap.getWidth()) / bitmap.getHeight();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //测量view的大小
            surfaceWidth = getDefaultSize(visibleScreenWidth, widthMeasureSpec);
            surfaceHeight = getDefaultSize(visibleScreenHieght, heightMeasureSpec);
            //没有调用父类的onMeasure则这个方法必须调用
            setMeasuredDimension(surfaceWidth, surfaceHeight);
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            running = true;

            //设置图片移动和缩放的最大与最小坐标
            leftMax = surfaceWidth / 2 - clipR;
            rightMin = surfaceWidth / 2 + clipR;
            topMax = surfaceHeight / 2 - clipR;
            bottomMin = surfaceHeight / 2 + clipR;

            //获取图片的大小
            bitmapWidth = bitmap.getWidth();
            bitmapHeight = bitmap.getHeight();

            //缩放bitmap尺寸
            if (bitmapWidth > surfaceWidth || bitmapHeight > surfaceHeight) {
                bitmapWidth = surfaceWidth;
                bitmapHeight = (int) (surfaceWidth / bitmapScale);
                if (bitmapHeight > surfaceHeight) {
                    bitmapHeight = surfaceHeight;
                    bitmapWidth = (int) (surfaceHeight * bitmapScale);
                }
            }

            int x0 = (surfaceWidth - bitmapWidth) / 2;
            int y0 = (surfaceHeight - bitmapHeight) / 2;
            int x1 = (surfaceWidth + bitmapWidth) / 2;
            int y1 = (surfaceHeight + bitmapHeight) / 2;
            //图片显示的区域
            zoomRect = new Rect(x0, y0, x1, y1);
            //要显示图片
            srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            bitW = bitmapWidth;
            bitH = bitmapHeight;
            clipXY = new int[]{surfaceWidth / 2, surfaceHeight / 2};

            new Thread(this).start();
        }


        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }


        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            running = false;
        }

        private Point point = new Point();//点击点

        private boolean canDrag = false;//判断是否点击在图片上,否则拖动无效

        private int offsetX = 0, offsetY = 0;//点击点离图片左上角的距离

        private float initDistance;

        private int dy;

        private int bitW, bitH;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.i("asd", "action=" + event.getAction());
            switch (event.getAction()) {
                //手按下的时候
                case MotionEvent.ACTION_DOWN:
                    state = move;
                    point.x = (int) event.getX();
                    point.y = (int) event.getY();
                    if (zoomRect.contains(point.x, point.y)) {
                        canDrag = true;
                        offsetX = point.x - zoomRect.left;
                        offsetY = point.y - zoomRect.top;
                    }
                    break;

                //移动的时候
                case MotionEvent.ACTION_MOVE:
                    if (!canDrag)
                        break;
                    if (state == move) {
                        zoomRect.left = (int) event.getX() - offsetX;
                        zoomRect.top = (int) event.getY() - offsetY;
                        zoomRect.right = zoomRect.left + bitW;
                        zoomRect.bottom = zoomRect.top + bitH;
                        if (zoomRect.left > leftMax) {
                            zoomRect.left = leftMax;
                            zoomRect.right = zoomRect.left + bitW;
                        }
                        if (zoomRect.right < rightMin) {
                            zoomRect.right = rightMin;
                            zoomRect.left = zoomRect.right - bitW;
                        }
                        if (zoomRect.top > topMax) {
                            zoomRect.top = topMax;
                            zoomRect.bottom = zoomRect.top + bitH;
                        }
                        if (zoomRect.bottom < bottomMin) {
                            zoomRect.bottom = bottomMin;
                            zoomRect.top = zoomRect.bottom - bitH;
                        }
                    } else if (state == zoom) {
                        float move = getDistance(event);
                        int dx0 = (int) (move - initDistance);
                        zoomRect.left -= dx0;
                        zoomRect.right += dx0;
                        if (zoomRect.left > leftMax || zoomRect.right < rightMin) {
                            zoomRect.left += dx0;
                            zoomRect.right -= dx0;
                            return true;
                        }
                        bitW = zoomRect.right - zoomRect.left;
                        bitH = (int) (bitW / bitmapScale);
                        int dy0 = (bitH - bitmapHeight) / 2;
                        int d1 = dy0 - dy;
                        zoomRect.top -= d1;
                        zoomRect.bottom += d1;
                        if (zoomRect.top > topMax || zoomRect.bottom < bottomMin) {
                            zoomRect.top += d1;
                            zoomRect.bottom -= d1;
                            zoomRect.left += dx0;
                            zoomRect.right -= dx0;
                            bitW = zoomRect.right - zoomRect.left;
                            bitH = (int) (bitW / bitmapScale);
                        } else {
                            initDistance = move;
                            dy = dy0;
                        }
                    }
                    break;
                case 261:
                    state = zoom;
                    initDistance = getDistance(event);
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    state = -1;
                    canDrag = false;
                    break;

                case MotionEvent.ACTION_UP:
                    state = -1;
                    canDrag = false;
                    break;
                default:
                    state = -1;
                    canDrag = false;
                    break;
            }
            return true;
        }


        @Override
        public void run() {
            //绘制裁剪框bitmap图片
            Paint paint = new Paint();
            //给画笔设置颜色
            paint.setAlpha(Color.TRANSPARENT);
            //设置画笔样式
            paint.setStyle(Paint.Style.FILL);
            //消除锯齿
            paint.setAntiAlias(true);
            //设置绘制图层的显示
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            //创建一个有尺寸的空的bitmap
            Bitmap bit = Bitmap.createBitmap(surfaceWidth, surfaceHeight, Bitmap.Config.ARGB_8888);
            //
            Canvas tempcCanvas = new Canvas(bit);
            tempcCanvas.drawColor(Color.parseColor("#55000000"));
            tempcCanvas.drawCircle(clipXY[0], clipXY[1], clipR, paint);

            while (running) {
                Canvas canvas = holder.lockCanvas();//获取画布
                if (canvas == null)
                    continue;
                //给你画布绘制颜色
                canvas.drawColor(Color.WHITE);
                //把图片绘制到画布上 srcRect:图片显示的大小,zoomRect:图片显示的区域
                canvas.drawBitmap(bitmap, srcRect, zoomRect, null);
                //裁剪框绘制到画布上
                canvas.drawBitmap(bit, 0, 0, null);
                holder.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像
            }
        }
    }

    //获取起始位置的距离
    private float getDistance(MotionEvent event) {
        float dx = event.getX(0) - event.getX(1);
        float dy = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(dx * dx + dy * dy);
    }
}


你可能感兴趣的:(Android,canvas,sufaceview,移动,裁剪)