天天看點

仿照原生系統的圖檔編輯,自定義控件,可以删除、挪動、放大縮小等

根據公司的要求,需要寫一個自定義圖檔編輯控件,可以放大縮小,删除,拖動等操作。

先寫一個自定義的控件StickerView代碼如下:

package com.ankoninc.imageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.ImageView;

import com.ankoninc.esdiagnose.R;

/**
 * Created by lihu on 2017/4/18.
 */
public class StickerView extends ImageView {

    private static final String Log_TAG = "DragImageView&&StickerView";
    //删除圖示
    private Bitmap deleteBitmap;
    //放大縮小圖示
    private Bitmap resizeBitmap;
    private Bitmap mBitmap;
    private Bitmap topBitmap;
    private Bitmap flipBitmap;

    private Rect dst_delete;
    private Rect dst_resize;
    private Rect dst_flipV;
    private int deleteBitmapWidth;
    private int deleteBitmapHeight;
    private int resizeBitmapWidth;
    private int resizeBitmapHeight;

    //水準鏡像
    private int flipVBitmapWidth;
    private int flipVBitmapHeight;
    //置頂
    private int topBitmapWidth;
    private int topBitmapHeight;

    private Paint localPaint;
    private int mScreenwidth;
    private int mScrernHeight;

    private PointF mid = new PointF();
    private float lastRotateDegree;

    private boolean isPointerDown = false;
    //手指移動距離必須超過這個數值
    private final float pointerLimitDis = 20f;
    private final float pointerZoomCoeff = 0.09f;
    /**
     * 對角線的長度
     */
    private float lastLength;

    private boolean isInResize = false;

    private Matrix matrix = new Matrix();
    /**
     * 是否在四條線的内部
     */
    private boolean isInSide;
    private float startX;
    private float startY;
    private float rightX;
    private float rightY;
    private float leftX;
    private float leftY;
    private float endX;
    private float endY;
    private float lastX, lastY;
    /**
     * 是否在編輯模式
     */
    private boolean isInEdit = true;

    private float MIN_SCALE = 0.5f;
    private float MAX_SCALE = 1.2f;

    private double halfDiagonalLength;

    private float oringinWidth = 0;

    //雙指縮放時的初始距離
    private float oldDis;

    private final long stickerId;

    private DisplayMetrics dm;

    private static final float BITMAP_SCALE = 0.7f;

    private OperationListener operationListener;

    public StickerView(Context context, MotionEvent event) {
        super(context);
        stickerId = 0;
        mEvent = event;
        init();
    }

    public StickerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        stickerId = 0;
        init();
    }

    private void init() {

        dst_delete = new Rect();
        dst_resize = new Rect();
        dst_flipV = new Rect();
        localPaint = new Paint();
        localPaint.setColor(getResources().getColor(R.color.transparent));
        localPaint.setAntiAlias(true);
        localPaint.setDither(true);
        localPaint.setStyle(Paint.Style.STROKE);
        localPaint.setStrokeWidth(2.0f);
        dm = getResources().getDisplayMetrics();//擷取螢幕參數
        mScreenwidth = dm.widthPixels;
        mScreenwidth = dm.heightPixels;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mBitmap != null) {

            float[] arrayOfFloat = new float[9];
            matrix.getValues(arrayOfFloat);
            float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
            float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
            float f3 = arrayOfFloat[0] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
            float f4 = arrayOfFloat[3] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
            float f5 = 0.0F * arrayOfFloat[0] + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2];
            float f6 = 0.0F * arrayOfFloat[3] + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5];
            float f7 = arrayOfFloat[0] * this.mBitmap.getWidth() + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2];
            float f8 = arrayOfFloat[3] * this.mBitmap.getWidth() + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5];

            canvas.save();
            canvas.drawBitmap(mBitmap, matrix, null);
            dst_delete.left = (int) (f1 - deleteBitmapWidth / 2);
            dst_delete.right = (int) (f1 + deleteBitmapWidth / 2);
            dst_delete.top = (int) (f2 - deleteBitmapHeight / 2);
            dst_delete.bottom = (int) (f2 + deleteBitmapHeight / 2);
            dst_resize.left = (int) (f7 - resizeBitmapWidth / 2);
            dst_resize.right = (int) (f7 + resizeBitmapWidth / 2);
            dst_resize.top = (int) (f8 - resizeBitmapHeight / 2);
            dst_resize.bottom = (int) (f8 + resizeBitmapHeight / 2);
            //确定儲存
            dst_flipV.left = (int) (f3 - flipVBitmapWidth / 2);
            dst_flipV.right = (int) (f3 + flipVBitmapWidth / 2);
            dst_flipV.top = (int) (f4 - flipVBitmapHeight / 2);
            dst_flipV.bottom = (int) (f4 + flipVBitmapHeight / 2);

            if (isInEdit) {
                RectF rectF = new RectF(f1, f2, f7, f8);
                canvas.drawRect(rectF, localPaint);
                canvas.drawBitmap(deleteBitmap, null, dst_delete, null);
                canvas.drawBitmap(resizeBitmap, null, dst_resize, null);
                canvas.drawBitmap(flipBitmap, null, dst_flipV, null);
                startX = f1;
                startY = f2;
                rightX = f3;
                rightY = f4;
                leftX = f5;
                leftY = f6;
                endX = f7;
                endY = f8;
            }
            canvas.restore();
        }
    }



    public float getStartX() {
        return startX;
    }

    public float getStartY() {
        return startY;
    }

    public float getRightX() {
        return rightX;
    }

    public float getRightY() {
        return rightY;
    }

    public float getLeftX() {
        return leftX;
    }

    public float getLeftY() {
        return leftY;
    }

    public float getEndX() {
        return endX;
    }

    public float getEndY() {
        return endY;
    }


    @Override
    public void setImageResource(int resId) {
        setBitmap(BitmapFactory.decodeResource(getResources(), resId));
    }

    private MotionEvent mEvent;

    public void setBitmap(Bitmap bitmap) {
        matrix.reset();
        mBitmap = getInitBitmap(bitmap);
        setDiagonalLength();
        initBitmaps();
        int w = mBitmap.getWidth();
        int h = mBitmap.getHeight();
        oringinWidth = w;
        float initScale = (MIN_SCALE + MAX_SCALE) / 16;
        matrix.postScale(initScale, initScale, w / 2, h / 2);
        //Y坐标為 (頂部操作欄+正方形圖)/2
        matrix.postTranslate(mEvent.getX() - 3 * w / 4, mEvent.getY() - 3 * h / 4);
        invalidate();
    }


    private void setDiagonalLength() {
        halfDiagonalLength = Math.hypot(mBitmap.getWidth(), mBitmap.getHeight()) / 2;
    }

    /**
     * 初始化 布局圖檔
     * @param image
     * @return
     */
    private Bitmap getInitBitmap(Bitmap image) {
        if (image == null) {
            return null;
        }

        Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = createDefaultPaint();
        float[] arrayOfFloat = new float[9];
        matrix.getValues(arrayOfFloat);
        float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
        float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
        float f3 = arrayOfFloat[0] * bitmap.getWidth() + arrayOfFloat[1] * bitmap.getHeight() + arrayOfFloat[2];
        float f4 = arrayOfFloat[3] * bitmap.getWidth() + arrayOfFloat[4] * bitmap.getHeight() + arrayOfFloat[5];
        RectF rectF = new RectF(f1, f2, f3, f4);
        canvas.drawRect(rectF, paint);
        canvas.drawBitmap(image, matrix, paint);
        return bitmap;
    }

    private Paint createDefaultPaint() {

        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.comTemplateButton0));

        paint.setStrokeWidth(getResources().getDimension(R.dimen.stcker_width));
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        return paint;
    }

    private void initBitmaps() {
        //當圖檔的寬比高大時 按照寬計算 縮放大小根據圖檔的大小而改變 最小為圖檔的1/8 最大為螢幕寬
        if (mBitmap.getWidth() >= mBitmap.getHeight()) {
            float minWidth = mScreenwidth / 24;
            if (mBitmap.getWidth() < minWidth) {
                MIN_SCALE = 1f;
            } else {
                MIN_SCALE = 1.0f * minWidth / mBitmap.getWidth();
            }

            if (mBitmap.getWidth() > mScreenwidth) {
                MAX_SCALE = 1f;
            } else {
                MAX_SCALE = 1.0f * mScreenwidth / mBitmap.getWidth();
            }
        } else {
            float minHeight = mScrernHeight / 24;

            if (mBitmap.getHeight() < minHeight) {
                MIN_SCALE = 1f;
            } else {
                MIN_SCALE = 1.0f * minHeight / mBitmap.getHeight();
            }

            if (mBitmap.getHeight() > mScreenwidth) {
                MAX_SCALE = 1f;
            } else {
                MAX_SCALE = 1.0f * mScreenwidth / mBitmap.getHeight();
            }
        }

        deleteBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_delete);
        resizeBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_resize);
        flipBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_flip);

        deleteBitmapWidth = (int) (deleteBitmap.getWidth() * BITMAP_SCALE);
        deleteBitmapHeight = (int) (deleteBitmap.getHeight() * BITMAP_SCALE);

        resizeBitmapWidth = (int) (resizeBitmap.getWidth() * BITMAP_SCALE);
        resizeBitmapHeight = (int) (resizeBitmap.getHeight() * BITMAP_SCALE);

        flipVBitmapWidth = (int) (flipBitmap.getWidth() * BITMAP_SCALE);
        flipVBitmapHeight = (int) (flipBitmap.getHeight() * BITMAP_SCALE);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = MotionEventCompat.getActionMasked(event);

        boolean handled = true;

        switch (action) {

            case MotionEvent.ACTION_DOWN:
                if (isInButton(event, dst_delete)) {
                    if (operationListener != null) {
                        operationListener.onDeleteClick();
                    }
                } else if (isInButton(event, dst_flipV)) {
                    if (operationListener != null) {
                        operationListener.drawRectLine();
                    }

                } else if (isInResize(event)) {

                    isInResize = true;
                    lastRotateDegree = rotationToStartPoint(event);
                    midPointToStartPoint(event); // 設定mid點的值
                    lastLength = diagonalLength(event);// 觸摸點到矩形中點的距離
                } else if (isInBitmap(event)) {
                    isInSide = true;
                    lastX = event.getX(0);
                    lastY = event.getY(0);
                } else {
                    handled = false;
                }
                break;
            case MotionEvent.ACTION_MOVE:

                //雙指縮放
                if (isPointerDown) {
                    float scale;
                    float disNew = spacing(event);

                    if (disNew == 0 || disNew < pointerLimitDis) {
                        scale = 1;
                    } else {
                        scale = disNew / oldDis;
                        //縮放緩慢
                        scale = (scale - 1) * pointerZoomCoeff + 1;
                    }

                    float scaleTemp = (scale * Math.abs(dst_delete.left - dst_resize.left)) / oringinWidth;
                    if ((scaleTemp <= MIN_SCALE) && scale < 1 || (scaleTemp >= MAX_SCALE) && scale > 1) {
                        scale = 1;
                    } else {
                        lastLength = diagonalLength(event);
                    }

                    matrix.postScale(scale, scale, mid.x, mid.y);
                    invalidate();
                } else if (isInResize) {

                    matrix.postRotate((rotationToStartPoint(event) - lastRotateDegree) * 2, mid.x, mid.y);
                    lastRotateDegree = rotationToStartPoint(event);
                    float scale = diagonalLength(event) / lastLength;

                    if (((diagonalLength(event) / halfDiagonalLength <= MIN_SCALE)) && scale < 1 ||
                            (diagonalLength(event) / halfDiagonalLength >= MAX_SCALE) && scale > 1) {
                        scale = 1;
                        if (!isInResize(event)) {
                            isInResize = false;
                        }
                    } else {
                        lastLength = diagonalLength(event);
                    }
                    matrix.postScale(scale, scale, mid.x, mid.y);
                    invalidate();
                } else if (isInSide) {
                    float x = event.getX(0);
                    float y = event.getY(0);
                    matrix.postTranslate(x - lastX, y - lastY);
                    lastX = x;
                    lastY = y;
                    invalidate();
                }
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                if (spacing(event) > pointerLimitDis) {
                    oldDis = spacing(event);
                    isPointerDown = true;
                    midPointToStartPoint(event);
                } else {
                    isPointerDown = false;
                }
                isInSide = false;
                isInResize = false;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                isInResize = false;
                isInSide = false;
                isPointerDown = false;
                break;
        }
        if (handled && operationListener != null) {
            operationListener.onEdit(this);
        }
        return handled;

    }

    private MotionEvent firstEvent;

    /**
     * 直接控制上層控件的改變,事件穿透,不用點選兩次
     *
     * @param event
     */
    public void inResize(MotionEvent event) {

        isInResize = true;
        if (firstEvent == null) {
            firstEvent = event;
            lastRotateDegree = rotationToStartPoint(firstEvent);
            midPointToStartPoint(firstEvent); // 設定mid點的值
            lastLength = diagonalLength(firstEvent);// 觸摸點到矩形中點的距離   todo 觸摸點 連續變化
        }

        matrix.postRotate((rotationToStartPoint(event) - lastRotateDegree) * 2, mid.x, mid.y);//旋轉
        lastRotateDegree = rotationToStartPoint(event);
        float scale = diagonalLength(event) / lastLength;

        if (((diagonalLength(event) / halfDiagonalLength <= MIN_SCALE)) && scale < 1 ||
                (diagonalLength(event) / halfDiagonalLength >= MAX_SCALE) && scale > 1) {
            scale = 1;
            if (!isInResize(event)) {
                isInResize = false;
            }
        } else {
            lastLength = diagonalLength(event);
        }
        matrix.postScale(scale, scale, mid.x, mid.y);//縮放
        invalidate();
    }

    /**
     * 計算圖檔的角度等屬性
     *
     * @param event
     * @return
     */
    private boolean isInBitmap(MotionEvent event) {

        float[] arrayOfFloat1 = new float[9];
        this.matrix.getValues(arrayOfFloat1);

        //左上角
        float f1 = 0.0F * arrayOfFloat1[0] + 0.0F * arrayOfFloat1[1] + arrayOfFloat1[2];
        float f2 = 0.0F * arrayOfFloat1[3] + 0.0F * arrayOfFloat1[4] + arrayOfFloat1[5];
        //右上角
        float f3 = arrayOfFloat1[0] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat1[1] + arrayOfFloat1[2];
        float f4 = arrayOfFloat1[3] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat1[4] + arrayOfFloat1[5];
        //左下角
        float f5 = 0.0F * arrayOfFloat1[0] + arrayOfFloat1[1] * this.mBitmap.getHeight() + arrayOfFloat1[2];
        float f6 = 0.0F * arrayOfFloat1[3] + arrayOfFloat1[4] * this.mBitmap.getHeight() + arrayOfFloat1[5];
        //右下角
        float f7 = arrayOfFloat1[0] * this.mBitmap.getWidth() + arrayOfFloat1[1] * this.mBitmap.getHeight() + arrayOfFloat1[2];
        float f8 = arrayOfFloat1[3] * this.mBitmap.getWidth() + arrayOfFloat1[4] * this.mBitmap.getHeight() + arrayOfFloat1[5];

        float[] arrayOfFloat2 = new float[4];
        float[] arrayOfFloat3 = new float[4];
        //确定X方向的範圍
        arrayOfFloat2[0] = f1;//左上的x
        arrayOfFloat2[1] = f3;//右上的x
        arrayOfFloat2[2] = f7;//右下的x
        arrayOfFloat2[3] = f5;//左下的x
        //确定Y方向的範圍
        arrayOfFloat3[0] = f2;//左上的y
        arrayOfFloat3[1] = f4;//右上的y
        arrayOfFloat3[2] = f8;//右下的y
        arrayOfFloat3[3] = f6;//左下的y
        return pointInRect(arrayOfFloat2, arrayOfFloat3, event.getX(0), event.getY(0));

    }

    /**
     * 判斷點是否在一個矩形内部
     *
     * @param xRange
     * @param yRange
     * @param x
     * @param y
     * @return
     */
    private boolean pointInRect(float[] xRange, float[] yRange, float x, float y) {
        //四條邊的長度
        double a1 = Math.hypot(xRange[0] - xRange[1], yRange[0] - yRange[1]);
        double a2 = Math.hypot(xRange[1] - xRange[2], yRange[1] - yRange[2]);
        double a3 = Math.hypot(xRange[3] - xRange[2], yRange[3] - yRange[2]);
        double a4 = Math.hypot(xRange[0] - xRange[3], yRange[0] - yRange[3]);
        //待檢測點到四個點的距離
        double b1 = Math.hypot(x - xRange[0], y - yRange[0]);
        double b2 = Math.hypot(x - xRange[1], y - yRange[1]);
        double b3 = Math.hypot(x - xRange[2], y - yRange[2]);
        double b4 = Math.hypot(x - xRange[3], y - yRange[3]);

        double u1 = (a1 + b1 + b2) / 2;
        double u2 = (a2 + b2 + b3) / 2;
        double u3 = (a3 + b3 + b4) / 2;
        double u4 = (a4 + b4 + b1) / 2;

        //矩形的面積
        double s = a1 * a2;
        //海倫公式 計算4個三角形面積
        double ss = Math.sqrt(u1 * (u1 - a1) * (u1 - b1) * (u1 - b2))
                + Math.sqrt(u2 * (u2 - a2) * (u2 - b2) * (u2 - b3))
                + Math.sqrt(u3 * (u3 - a3) * (u3 - b3) * (u3 - b4))
                + Math.sqrt(u4 * (u4 - a4) * (u4 - b4) * (u4 - b1));
        return Math.abs(s - ss) < 0.5;
    }

    /**
     * 觸摸是否在某個button範圍
     *
     * @param event
     * @param rect
     * @return
     */
    private boolean isInButton(MotionEvent event, Rect rect) {
        int left = rect.left;
        int right = rect.right;
        int top = rect.top;
        int bottom = rect.bottom;
        return event.getX(0) >= left && event.getX(0) <= right && event.getY(0) >= top && event.getY(0) <= bottom;
    }

    /**
     * 觸摸是否在拉伸區域内
     *
     * @param event
     * @return
     */
    private boolean isInResize(MotionEvent event) {
        int left = -20 + this.dst_resize.left;
        int top = -20 + this.dst_resize.top;
        int right = 20 + this.dst_resize.right;
        int bottom = 20 + this.dst_resize.bottom;
        return event.getX(0) >= left && event.getX(0) <= right && event.getY(0) >= top && event.getY(0) <= bottom;
    }

    /**
     * 觸摸的位置和圖檔左上角位置的中點
     *
     * @param event
     */
    private void midPointToStartPoint(MotionEvent event) {
        float[] arrayOfFloat = new float[9];
        matrix.getValues(arrayOfFloat);
        float f1 = 0.0f * arrayOfFloat[0] + 0.0f * arrayOfFloat[1] + arrayOfFloat[2];
        float f2 = 0.0f * arrayOfFloat[3] + 0.0f * arrayOfFloat[4] + arrayOfFloat[5];
        float f3 = f1 + event.getX(0);
        float f4 = f2 + event.getY(0);
        mid.set(f3 / 2, f4 / 2);
    }

    /**
     * 計算對角線交叉的位置
     *
     * @param paramPointF
     */
    private void midDiagonalPoint(PointF paramPointF) {
        float[] arrayOfFloat = new float[9];
        this.matrix.getValues(arrayOfFloat);
        float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
        float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
        float f3 = arrayOfFloat[0] * this.mBitmap.getWidth() + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2];
        float f4 = arrayOfFloat[3] * this.mBitmap.getWidth() + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5];
        float f5 = f1 + f3;
        float f6 = f2 + f4;
        paramPointF.set(f5 / 2.0F, f6 / 2.0F);
    }

    /**
     * 在滑動旋轉過程中,總是以左上角原點作為絕對坐标計算偏轉角度
     *
     * @param event
     * @return
     */
    private float rotationToStartPoint(MotionEvent event) {

        float[] arrayOfFloat = new float[9];
        matrix.getValues(arrayOfFloat);
        float x = 0.0f * arrayOfFloat[0] + 0.0f * arrayOfFloat[1] + arrayOfFloat[2];
        float y = 0.0f * arrayOfFloat[3] + 0.0f * arrayOfFloat[4] + arrayOfFloat[5];
        double arc = Math.atan2(event.getY(0) - y, event.getX(0) - x);
        return (float) Math.toDegrees(arc);
    }

    /**
     * 觸摸點到矩形中點的距離
     *
     * @param event
     * @return
     */
    private float diagonalLength(MotionEvent event) {
        float diagonalLength = (float) Math.hypot(event.getX(0) - mid.x, event.getY(0) - mid.y);
        return diagonalLength;
    }

    /**
     * 計算雙指之間的距離
     */
    private float spacing(MotionEvent event) {
        if (event.getPointerCount() == 2) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return (float) Math.sqrt(x * x + y * y);
        } else {
            return 0;
        }
    }

    public interface OperationListener {
        void onDeleteClick();
        void onEdit(StickerView stickerView);
        void drawRectLine();
    }

    public void setOperationListener(OperationListener operationListener) {
        this.operationListener = operationListener;
    }

    public void setInEdit(boolean isInEdit) {
        this.isInEdit = isInEdit;
        invalidate();
    }

}
           

在我們的項目當中,需要映射到另一張圖檔上

package com.ankoninc.imageview;

/**
 * Created by Nick.Zhang on 2015/3/11.
 */

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.ankoninc.data.PointInfo;
import com.ankoninc.esdiagnose.AppContext;
import com.ankoninc.esdiagnose.R;
import com.ankoninc.utils.DensityUtils;
import com.ankoninc.utils.Log;

import java.util.ArrayList;
import java.util.List;

public class DragImageView extends ImageView {

    private static final String LOG_TAG = "DragImageView";

    private static final int DEFAULT_IMAGE_SIZE = 480;
    private static final int LINE_STROKE_WIDTH = DensityUtils.dp2px(AppContext.getInstance(), 2);
    private static final int FONT_SIZE = DensityUtils.dp2px(AppContext.getInstance(), 10);
    private static final int TEXT_COLOR = Color.BLUE;
    private static final int LINE_COLOR = 0xffffd10c;

    public Bitmap mSrcBitmap;
    public Bitmap tmpBitmap;
    public Bitmap mDrawBitmap;
    public boolean mEdit = false;
    public List<PointInfo> mPointList = new ArrayList<PointInfo>();
    public MARK mark = MARK.NONE;// 預設模式
    private Rect currentRect = new Rect();
    private PointF drawStartPoint = new PointF();
    private PointF drawCurrentPoint = new PointF();
    private PointF startPoint0 = new PointF();
    private PointF startPoint1 = new PointF();
    private PointF currentPoint0 = new PointF();
    private float startLen;
    private float currentLen;
    private int minImageSize = DEFAULT_IMAGE_SIZE;
    private int mDragWidth = 0;
    private int mDragHeight = 0;
    private MODE mode = MODE.NONE;// 預設模式

    private RelativeLayout mRelativeLayout;

    //設定開關,隻允許畫一次矩形
    boolean isDragRect;
    //目前的正方形的控件
    private StickerView mCurrentView;

    public DragImageView(Context context) {
        this(context, null);
    }

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

    public void setMark(MARK type) {
        Log.d(LOG_TAG, "setMark: %s", type);
        mark = type;
    }

    private Context mContext;

    public void setRelativeLayout(RelativeLayout relativeLayout, Context context) {
        this.mRelativeLayout = relativeLayout;
        this.mContext = context;
    }

    public void setBitmapSrc(Bitmap src, List<PointInfo> pointList) {
        Log.d(LOG_TAG, "setBitmapSrc: %s, %s", src, pointList);
        mPointList = pointList;
        mDrawBitmap = drawMarkImage(src, mPointList);
        mSrcBitmap = src;
        tmpBitmap = mDrawBitmap;
        this.setImageBitmap(mDrawBitmap);
    }

    public void setDragSize(int width, int height) {
        Log.d(LOG_TAG, "setDragSize: %s, %s", width, height);
        int tmp = Math.abs(width - height);

        this.setFrame(tmp / 2, 0, width - tmp / 2, height);
        this.layout(tmp / 2, 0, width - tmp / 2, height);
        mDragWidth = width;
        mDragHeight = height;
    }

    public void resetBitmap() {
        Log.d(LOG_TAG, "resetBitmap");
        mDrawBitmap = mSrcBitmap;
        tmpBitmap = mDrawBitmap;
        mPointList.clear();
        this.setImageBitmap(mSrcBitmap);
        mEdit = false;
    }

    /**
     * 編輯模式中重置開關,重置最後一次操作
     */
    public void cancelLastDraw() {

        if (mPointList == null || mPointList.size() <= 1) {
            resetBitmap();
            return;
        }

        int last = mPointList.size() - 1;
        mPointList.remove(last);
        setBitmapSrc(mSrcBitmap, mPointList);
    }

    /**
     * 設定顯示圖檔
     */
    @Override
    public void setImageBitmap(Bitmap bm) {
        Log.d(LOG_TAG, "setImageBitmap: %s", bm);
        if (mode == MODE.NONE) {
            Log.d(LOG_TAG, "setImageBitmap only save bitmap without mark.");
            mDrawBitmap = bm;
        }
        super.setImageBitmap(bm);
    }

    /**
     * touch 事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        Log.d(LOG_TAG, "onTouchEvent");
        Log.d(LOG_TAG, "rawX: %s, rawY: %s, X: %s, Y: %s",
                event.getRawX(), event.getRawY(), event.getX(), event.getY());

        /** 處理單點、多點觸摸 **/
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                Log.d(LOG_TAG, "ACTION_DOWN");
                onTouchDown(event);
                break;
            // 多點觸摸
            case MotionEvent.ACTION_POINTER_DOWN:
                Log.d(LOG_TAG, "ACTION_POINTER_DOWN");
                onPointerDown(event);
                break;

            case MotionEvent.ACTION_MOVE:
                Log.d(LOG_TAG, "ACTION_MOVE");
                onTouchMove(event);
                break;
            case MotionEvent.ACTION_UP:
                isDragRect = false;
                Log.d(LOG_TAG, "ACTION_UP");
                if (mark != MARK.NONE && mode == MODE.DRAG) {
                    Log.d(LOG_TAG, "Add a new tag info");
                    PointInfo info = new PointInfo();
                    if (mark != MARK.RECT) {
                        info.setType(mark);
                        // TODO: 2017/4/24  區分開是矩形還是其他的形狀
                        PointF startPoint = new PointF();
                        PointF endPoint = new PointF();
                        if (mark == MARK.ARROW || mark == MARK.MEASURE || mark == MARK.CIRCLE) {
                            startPoint.set((drawStartPoint.x * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth(), (drawStartPoint.y * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth());
                            endPoint.set((drawCurrentPoint.x * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth(), (drawCurrentPoint.y * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth());
                            info.setStartPoint(startPoint);
                            info.setEndPoint(endPoint);
                        }
                        mPointList.add(info);
                    }
                }
                mode = MODE.NONE;
                this.setImageBitmap(tmpBitmap);

                break;
            // 多點松開
            case MotionEvent.ACTION_POINTER_UP:
                Log.d(LOG_TAG, "ACTION_POINTER_UP");
                mode = MODE.NONE;
                break;
        }

        return true;
    }

    /**
     * 繪制圖檔, 加載時繪圖
     *
     * @param image
     * @param pointList
     * @return
     */
    public static Bitmap drawMarkImage(Bitmap image, List<PointInfo> pointList) {
        Log.d(LOG_TAG, "drawMarkImage: %s, %s", image, pointList);

        if (image == null || pointList == null || pointList.isEmpty()) {
            return image;
        }

        Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);
        Paint paint = createDefaultPaint(Math.min(image.getWidth(), image.getHeight()));
        canvas.drawBitmap(image, 0, 0, paint);

        for (PointInfo pointInfo : pointList) {
            PointF startPoint = pointInfo.getStartPoint();
            PointF endPoint = pointInfo.getEndPoint();
            PointF start = new PointF();
            PointF end = new PointF();
            if (startPoint != null && endPoint != null) {
                start.set(startPoint.x * image.getWidth() / DEFAULT_IMAGE_SIZE, startPoint.y * image.getHeight() / DEFAULT_IMAGE_SIZE);
                end.set(endPoint.x * image.getWidth() / DEFAULT_IMAGE_SIZE, endPoint.y * image.getHeight() / DEFAULT_IMAGE_SIZE);

                MARK type = pointInfo.getType();
                switch (type) {
                    case ARROW:
                        // 設定畫箭頭的style為實心
                        paint.setStyle(Paint.Style.FILL_AND_STROKE);
                        requestDrawAL(start.x, start.y, end.x, end.y, canvas, paint);
                        break;
                    case MEASURE:
                        paint.setStyle(Paint.Style.FILL_AND_STROKE);
                        measureAndDraw(start.x, start.y, end.x, end.y, canvas, paint);
                        break;
                    case CIRCLE:
                        RectF oval = new RectF(start.x, start.y, end.x, end.y);
                        Log.d(LOG_TAG, "start.x: %s, start.y: %s, end.x: %s, end.y: %s", start.x, start.y, end.x, end.y);
                        paint.setStyle(Paint.Style.STROKE);
                        canvas.drawOval(oval, paint);
                        break;
                    case RECT:
                        PointF leftPoint = pointInfo.getLeftPoint();
                        PointF rightPoint = pointInfo.getRightPoint();
                        PointF left = new PointF();
                        PointF right = new PointF();
                        left.set(leftPoint.x * image.getWidth() / DEFAULT_IMAGE_SIZE, leftPoint.y * image.getHeight() / DEFAULT_IMAGE_SIZE);
                        right.set(rightPoint.x * image.getWidth() / DEFAULT_IMAGE_SIZE, rightPoint.y * image.getHeight() / DEFAULT_IMAGE_SIZE);
                        canvas.drawLine(start.x, start.y, right.x, right.y, paint);
                        canvas.drawLine(right.x, right.y, end.x, end.y, paint);
                        canvas.drawLine(left.x, left.y, end.x, end.y, paint);
                        canvas.drawLine(left.x, left.y, start.x, start.y, paint);

                        break;
                    default:
                        break;
                }
            }
        }

        return bitmap;
    }

    /**
     * 按下 *
     */
    void onTouchDown(MotionEvent event) {
        Log.d(LOG_TAG, "onTouchDown");
        mode = MODE.DRAG;
        currentRect.set(this.getLeft(), this.getTop(), this.getRight(), this.getBottom());
        startPoint0.set(event.getRawX(), event.getRawY());
        drawStartPoint.set(event.getX(), event.getY());

        if (mark == MARK.RECT) {
            if (!isDragRect) {
                isDragRect = true;
                addRectView(event);

            }
        }

    }

    /**
     * 兩個手指 隻能放大縮小 *
     */
    void onPointerDown(MotionEvent event) {
        Log.d(LOG_TAG, "onPointerDown PointerCount: %s", event.getPointerCount());
        if (event.getPointerCount() == 2) {
            mode = MODE.ZOOM;
            startLen = getDistance(event);
            startPoint1.set(event.getRawX(), event.getRawY());
        }
    }

    private static void requestDrawAL(float sx, float sy, float ex, float ey, Canvas canvas, Paint paint) {

        requestDrawAL(sx, sy, ex, ey, false, true, canvas, paint);
    }

    private static void requestDrawAL(float sx, float sy, float ex, float ey,
                                      boolean drawStartArrow, boolean drawEndArrow, Canvas canvas, Paint paint) {

        int imageSize = Math.min(canvas.getWidth(), canvas.getHeight());
        double L = Math.max(LINE_STROKE_WIDTH * imageSize / DEFAULT_IMAGE_SIZE, 1); // 底邊的一半
        double H = 2 * L + 1; // 箭頭高度
        double awrad = Math.atan(L / H); // 箭頭角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭頭的長度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3, y_3, x_4, y_4;
        Path triangle;

        // 畫起點三角形
        if (drawStartArrow) {
            x_3 = sx + arrXY_1[0]; // (x3,y3)是第一端點
            y_3 = sy + arrXY_1[1];
            x_4 = sx + arrXY_2[0]; // (x4,y4)是第二端點
            y_4 = sy + arrXY_2[1];
            triangle = new Path();
            triangle.setFillType(Path.FillType.EVEN_ODD);
            triangle.moveTo(sx, sy);
            triangle.lineTo(safeParseDouble(x_3), safeParseDouble(y_3));
            triangle.lineTo(safeParseDouble(x_4), safeParseDouble(y_4));
            triangle.close();
            canvas.drawPath(triangle, paint);
        }

        // 畫線
        canvas.drawLine(sx, sy, ex, ey, paint);

        // 畫終點三角形
        if (drawEndArrow) {
            x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端點
            y_3 = ey - arrXY_1[1];
            x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端點
            y_4 = ey - arrXY_2[1];

            triangle = new Path();
            triangle.setFillType(Path.FillType.EVEN_ODD);
            triangle.moveTo(ex, ey);
            triangle.lineTo(safeParseDouble(x_3), safeParseDouble(y_3));
            triangle.lineTo(safeParseDouble(x_4), safeParseDouble(y_4));
            triangle.close();
            canvas.drawPath(triangle, paint);
        }
    }

    private static void measureAndDraw(float sx, float sy, float ex, float ey, Canvas canvas, Paint paint) {

        requestDrawAL(sx, sy, ex, ey, true, true, canvas, paint);

        int x0 = safeParseDouble(sx * DEFAULT_IMAGE_SIZE / canvas.getWidth());
        int y0 = safeParseDouble(sy * DEFAULT_IMAGE_SIZE / canvas.getHeight());
        int x1 = safeParseDouble(ex * DEFAULT_IMAGE_SIZE / canvas.getWidth());
        int y1 = safeParseDouble(ey * DEFAULT_IMAGE_SIZE / canvas.getHeight());
        double distance = getAllDistance(x0, y0, x1, y1);
        Log.d(LOG_TAG, "distance: %s", distance);
        String text = String.format("%.1fmm", distance);
        int imageSize = Math.min(canvas.getWidth(), canvas.getHeight());
        Paint textPaint = createTextPaint(imageSize);
        float width = textPaint.measureText(text);
        float pathWidth = Math.abs(ex - sx);
        float textSx, textSy, textEx, textEy;
        if (sx < ex) {
            textSx = sx;
            textSy = sy;
            textEx = ex;
            textEy = ey;
        } else {
            textSx = ex;
            textSy = ey;
            textEx = sx;
            textEy = sy;
        }

        if (width > pathWidth) {
            float step = (width - pathWidth) / 2 + 1;
            if (Math.abs(ex - sx) < 1) {
                textSy = Math.min(textSy, textEy) - step;
                textEy = Math.max(textSy, textEy) + step;
            } else if (Math.abs(ey - sy) < 1) {
                textSx = textSx - step;
                textEx = textEx + step;
            } else {
                float stepY = step * Math.abs(ey - sy) / Math.abs(ex - sx);
                textSx = textSx - step;
                textSy = textSy - (textSy < textEy ? 1 : -1) * stepY;
                textEx = textEx + step;
                textEy = textEy + (textEy > textSy ? 1 : -1) * stepY;
            }
        }
        Log.d(LOG_TAG, "Raw(%s, %s), (%s, %s), Text(%s, %s), (%s, %s)", sx, sy, ex, ey, textSx, textSy, textEx, textEy);
        Path path = new Path();
        path.moveTo(textSx, textSy);
        path.lineTo(textEx, textEy);
        canvas.drawTextOnPath(text, path, 0, 0, textPaint);
    }

    private static double getAllDistance(int x0, int y0, int x1, int y1) {

        double distance0 = 0.0000f;
        double distance1 = 0.0000f;
        Point c = new Point();
        int tmpAx, tmpAy, tmpBx, tmpBy;
        int center = DEFAULT_IMAGE_SIZE / 2;
        tmpAx = Math.abs(x0 - center);
        tmpAy = Math.abs(y1 - center);
        tmpBx = Math.abs(x1 - center);
        tmpBy = Math.abs(y0 - center);
        if ((tmpAx * tmpAx + tmpAy * tmpAy) >= (tmpBx * tmpBx + tmpBy * tmpBy)) {
            c.set(x1, y0);
        } else {
            c.set(x0, y1);
        }
        if (x0 == x1) {
            for (int i = Math.min(y0, y1); i <= Math.max(y0, y1); i++) {
                distance1 += getPixelDistance(x0, i);
            }
        } else if (y0 == y1) {
            for (int i = Math.min(x0, x1); i <= Math.max(x0, x1); i++) {
                distance0 += getPixelDistance(i, y0);
            }
        } else {
            if (c.x == x0) {
                for (int i = Math.min(x0, x1); i <= Math.max(x0, x1); i++) {
                    distance0 += getPixelDistance(i, c.y);
                }
                for (int i = Math.min(c.y, y0); i <= Math.max(c.y, y0); i++) {
                    distance1 += getPixelDistance(x0, i);
                }
            } else if (c.x == x1) {
                for (int i = Math.min(x0, x1); i <= Math.max(x0, x1); i++) {
                    distance0 += getPixelDistance(i, c.y);
                }
                for (int i = Math.min(c.y, y1); i <= Math.max(c.y, y1); i++) {
                    distance1 += getPixelDistance(x0, i);
                }
            }
        }

        return Math.sqrt(distance0 * distance0 + distance1 * distance1);
    }

    private static double getPixelDistance(int x0, int y0) {
        int tmpX, tmpY;
        double a = 0.0241f;
        double t1 = 0.000026695f;
        double t2 = 0.0353f;
        double m, distance;

        tmpX = Math.abs(240 - x0);
        tmpY = Math.abs(240 - y0);
        m = Math.sqrt(tmpX * tmpX + tmpY * tmpY);
        distance = a + t1 * Math.exp(t2 * m);
        if (distance > 0.08) {
            distance = 0.08;
        }
        return distance;
    }

    private static int safeParseDouble(double value) {
        Double result = value;
        return result.intValue();
    }

    private static double[] rotateVec(float px, float py, double ang, boolean isChLen, double newLen) {
        double mathstr[] = new double[2];

        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }

    private static Paint createDefaultPaint(int imageSize) {

        Paint paint = new Paint();
        paint.setColor(LINE_COLOR);
        int lineWidth = LINE_STROKE_WIDTH * imageSize / DEFAULT_IMAGE_SIZE;
        paint.setStrokeWidth(Math.max(lineWidth, 1));
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        return paint;
    }

    private static Paint createTextPaint(int imageSize) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(TEXT_COLOR);
        int fontSize = FONT_SIZE * imageSize / DEFAULT_IMAGE_SIZE;
        paint.setTextSize(Math.max(fontSize, 10));
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        return paint;
    }

    /**
     * 移動的處理 *
     */
    void onTouchMove(MotionEvent event) {
        Log.d(LOG_TAG, "onTouchMove begin");
        if (mode == MODE.DRAG) {

            Log.d(LOG_TAG, "onTouchMove in MODE.DRAG");
            currentPoint0.set(event.getRawX(), event.getRawY());
            drawCurrentPoint.set(event.getX(), event.getY());
            int x = (int) (currentPoint0.x - startPoint0.x);
            int y = (int) (currentPoint0.y - startPoint0.y);
            Log.d(LOG_TAG, "distance x: %s, y: %s", x, y);
            if (mark == MARK.NONE) {
                if (mCurrentView != null) {
                    mCurrentView.setInEdit(false);

                }
                Log.d(LOG_TAG, "onTouchMove with MARK.NONE");
                int left = currentRect.left + x;
                int top = currentRect.top + y;
                int right = currentRect.right + x;
                int bottom = currentRect.bottom + y;
                Log.d(LOG_TAG, "before left: %s, top: %s, right: %s, bottom: %s",
                        left, top, right, bottom);
                if (left < -this.getWidth() / 2) {
                    left = -this.getWidth() / 2;
                    right = this.getWidth() / 2;
                } else if (right > mDragWidth + this.getWidth() / 2) {
                    left = mDragWidth - this.getWidth() / 2;
                    right = mDragWidth + this.getWidth() / 2;
                }
                if (top < -this.getHeight() / 2) {
                    top = -this.getHeight() / 2;
                    bottom = this.getHeight() / 2;
                } else if (bottom > mDragHeight + this.getWidth() / 2) {
                    top = mDragHeight - this.getHeight() / 2;
                    bottom = mDragHeight + this.getHeight() / 2;
                }
                Log.d(LOG_TAG, "after left: %s, top: %s, right: %s, bottom: %s",
                        left, top, right, bottom);
                this.layout(left, top, right, bottom);

            } else if ((x * x + y * y) > 100 && (mark == MARK.ARROW || mark == MARK.MEASURE || mark == MARK.CIRCLE)) {

                Bitmap dest = Bitmap.createBitmap(mDrawBitmap.getWidth(), mDrawBitmap.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(dest);
                Paint paint = createDefaultPaint(Math.max(mDrawBitmap.getWidth(), mDrawBitmap.getHeight()));
                canvas.drawBitmap(mDrawBitmap, 0, 0, paint);
                if (mCurrentView != null) {
                    mCurrentView.setInEdit(false);
                }
                float sx = drawStartPoint.x * mSrcBitmap.getWidth() / this.getWidth();
                float sy = drawStartPoint.y * mSrcBitmap.getHeight() / this.getHeight();
                float ex = drawCurrentPoint.x * mSrcBitmap.getWidth() / this.getWidth();
                float ey = drawCurrentPoint.y * mSrcBitmap.getHeight() / this.getHeight();

                if (mark == MARK.CIRCLE) {
                    Log.d(LOG_TAG, "onTouchMove with MARK.CIRCLE and moved a distance");
                    RectF oval = new RectF(sx, sy, ex, ey);
                    canvas.drawOval(oval, paint);
                } else {
                    Log.d(LOG_TAG, "onTouchMove with MARK.ARROW and moved a distance");
                    // 設定畫箭頭的paint為實心
                    paint.setStyle(Paint.Style.FILL_AND_STROKE);
                    if (mark == MARK.MEASURE) {
                        measureAndDraw(sx, sy, ex, ey, canvas, paint);
                    } else {
                        requestDrawAL(sx, sy, ex, ey, canvas, paint);
                    }
                }

                this.setImageBitmap(dest);
                tmpBitmap = dest;
                mEdit = true;
            } else if (mark == MARK.RECT) {
                // TODO: 2017/4/20  拖動 頂層控件
                mCurrentView.inResize(event);
            }
        } else if (mode == MODE.ZOOM) {
            Log.d(LOG_TAG, "onTouchMove in MODE.ZOOM");
            currentLen = getDistance(event);
            float scale = currentLen - startLen;
            int size = (int) scale;
            if ((currentRect.right - currentRect.left + 2 * size) > minImageSize) {
                this.setFrame(currentRect.left - size, currentRect.top - size, currentRect.right + size, currentRect.bottom + size);
            }
        }
        Log.d(LOG_TAG, "onTouchMove finish");
    }

    public void closeRect() {
        if (mCurrentView != null) {
            mRelativeLayout.removeView(mCurrentView);
        }
    }
    /**
     * 添加 矩形
     */
    private void addRectView(MotionEvent event) {
        final StickerView stickerView = new StickerView(mContext, event);
        stickerView.setImageResource(R.drawable.draw_rect);
        stickerView.setOperationListener(new StickerView.OperationListener() {
            @Override
            public void onDeleteClick() {
                mRelativeLayout.removeView(stickerView);

            }

            @Override
            public void onEdit(StickerView stickerView) {
                mCurrentView.setInEdit(false);
                mCurrentView = stickerView;// 這裡是新舊交換
                mCurrentView.setInEdit(true);
            }

            @Override
            public void drawRectLine() {
                drawRect();
                mRelativeLayout.removeView(stickerView);
            }
        });
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        mRelativeLayout.addView(stickerView, lp);
        setCurrentEdit(stickerView);

    }

    /**
     * 當點選确定時畫矩形,添加新的矩形時畫上一個矩形
     */
    private void drawRect() {
        Bitmap dest = Bitmap.createBitmap(mDrawBitmap.getWidth(), mDrawBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(dest);
        Paint paint = createDefaultPaint(Math.max(mDrawBitmap.getWidth(), mDrawBitmap.getHeight()));
        canvas.drawBitmap(mDrawBitmap, 0, 0, paint);

        PointInfo info = new PointInfo();
        info.setType(mark);
        // 計算4個頂點的位置
        float startx = (mCurrentView.getStartX() * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float starty = (mCurrentView.getStartY() * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float rightx = (mCurrentView.getRightX() * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float righty = (mCurrentView.getRightY() * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float leftx = (mCurrentView.getLeftX() * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float lefty = (mCurrentView.getLeftY() * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float endx = (mCurrentView.getEndX() * mSrcBitmap.getWidth() / this.getWidth()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        float endy = (mCurrentView.getEndY() * mSrcBitmap.getHeight() / this.getHeight()) * DEFAULT_IMAGE_SIZE / mSrcBitmap.getWidth();
        PointF startPoint = new PointF();
        PointF endPoint = new PointF();
        PointF rightPoint = new PointF();
        PointF leftPoint = new PointF();
        if (mark == MARK.RECT) {

            startPoint.set(startx, starty);
            rightPoint.set(rightx, righty);
            leftPoint.set(leftx, lefty);
            endPoint.set(endx, endy);

            info.setStartPoint(startPoint);
            info.setEndPoint(endPoint);
            info.setRightPoint(rightPoint);
            info.setLeftPoint(leftPoint);
        }
        mPointList.add(info);
        mode = MODE.NONE;
        // 畫正方形,因為控件是一個正方形,是以隻能畫四條邊
        canvas.drawLine(startx, starty, rightx, righty, paint);
        canvas.drawLine(rightx, righty, endx, endy, paint);
        canvas.drawLine(leftx, lefty, endx, endy, paint);
        canvas.drawLine(leftx, lefty, startx, starty, paint);
        this.setImageBitmap(dest);
        tmpBitmap = dest;
        mEdit = true;
    }

    /**
     * 設定目前處于編輯模式的貼紙
     */
    private void setCurrentEdit(StickerView stickerView) {
        if (mCurrentView != null) {
            mCurrentView.setInEdit(false);
        }

        mCurrentView = stickerView;
        stickerView.setInEdit(true);
    }

    /**
     * 擷取兩點的距離 *
     */
    float getDistance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);

        return FloatMath.sqrt(x * x + y * y);
    }

    private enum MODE {
        NONE, DRAG, ZOOM
    }

    public enum MARK {
        // 不要修改名稱,因為acil裡面存的就是string型的名稱,而不是id,改名稱之後容易比對不到類型
        NONE, ARROW, CIRCLE, MEASURE, RECT;

        public static MARK get(int ordinal) {

            for (MARK mark : MARK.values()) {
                if (mark.ordinal() == ordinal) {
                    return mark;
                }
            }

            return NONE;
        }
    }


}