1. 程式人生 > >Android對圖片進行平移,縮放,旋轉操作

Android對圖片進行平移,縮放,旋轉操作

package com.app.freestyle;



import java.util.Arrays;
import java.util.Collections;
import java.util.List;


import com.app.freestyle.R;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;


public class SingleTouchView extends View {
/** 
     * 圖片的最大縮放比例 
     */  
    public static final float MAX_SCALE = 4.0f;  
      
    /** 
     * 圖片的最小縮放比例 
     */  
    public static final float MIN_SCALE = 0.3f;  
      
    /** 
     * 控制縮放,旋轉圖示所在四個點得位置 
     */  
    public static final int LEFT_TOP = 0;  
    public static final int RIGHT_TOP = 1;  
    public static final int RIGHT_BOTTOM = 2;  
    public static final int LEFT_BOTTOM = 3;  
      
    /** 
     * 一些預設的常量 
     */  
    public static final int DEFAULT_FRAME_PADDING = 8;  
    public static final int DEFAULT_FRAME_WIDTH = 2;  
    public static final int DEFAULT_FRAME_COLOR = Color.WHITE;  
    public static final float DEFAULT_SCALE = 1.0f;  
    public static final float DEFAULT_DEGREE = 0;  
    public static final int DEFAULT_CONTROL_LOCATION = RIGHT_TOP;  
    public static final boolean DEFAULT_EDITABLE = true;  
    public static final int DEFAULT_OTHER_DRAWABLE_WIDTH = 50;  
    public static final int DEFAULT_OTHER_DRAWABLE_HEIGHT = 50;  
      
      
      
    /** 
     * 用於旋轉縮放的Bitmap 
     */  
    private Bitmap mBitmap;  
      
    /** 
     * SingleTouchView的中心點座標,相對於其父類佈局而言的 
     */  
    private PointF mCenterPoint = new PointF();  
      
    /** 
     * View的寬度和高度,隨著圖片的旋轉而變化(不包括控制旋轉,縮放圖片的寬高) 
     */  
    private int mViewWidth, mViewHeight;  
      
    /** 
     * 圖片的旋轉角度 
     */  
    private float mDegree = DEFAULT_DEGREE;  
      
    /** 
     * 圖片的縮放比例 
     */  
    private float mScale = DEFAULT_SCALE;  
      
    /** 
     * 用於縮放,旋轉,平移的矩陣 
     */  
    private Matrix matrix = new Matrix();  
      
    /** 
     * SingleTouchView距離父類佈局的左間距 
     */  
    private int mViewPaddingLeft;  
      
    /** 
     * SingleTouchView距離父類佈局的上間距 
     */  
    private int mViewPaddingTop;  
      
    /** 
     * 圖片四個點座標 
     */  
    private Point mLTPoint;  
    private Point mRTPoint;  
    private Point mRBPoint;  
    private Point mLBPoint;  
      
    /** 
     * 用於縮放,旋轉的控制點的座標 
     */  
    private Point mControlPoint = new Point();  
      
    /** 
     * 用於縮放,旋轉的圖示 
     */  
    private Drawable controlDrawable;  
      
    /** 
     * 縮放,旋轉圖示的寬和高 
     */  
    private int mDrawableWidth, mDrawableHeight;  
      
    /** 
     * 畫外圍框的Path 
     */  
    private Path mPath = new Path();  
      
    /** 
     * 畫外圍框的畫筆 
     */  
    private Paint mPaint ;  
      
    /** 
     * 初始狀態 
     */  
    public static final int STATUS_INIT = 0;  
      
    /** 
     * 拖動狀態 
     */  
    public static final int STATUS_DRAG = 1;  
      
    /** 
     * 旋轉或者放大狀態 
     */  
    public static final int STATUS_ROTATE_ZOOM = 2;   
      
    /** 
     * 當前所處的狀態 
     */  
    private int mStatus = STATUS_INIT;  
      
    /** 
     * 外邊框與圖片之間的間距, 單位是dip 
     */  
    private int framePadding = DEFAULT_FRAME_PADDING;  
      
    /** 
     * 外邊框顏色 
     */  
    private int frameColor = DEFAULT_FRAME_COLOR;  
      
    /** 
     * 外邊框線條粗細, 單位是 dip 
     */  
    private int frameWidth = DEFAULT_FRAME_WIDTH;  
      
    /** 
     * 是否處於可以縮放,平移,旋轉狀態 
     */  
    private boolean isEditable = DEFAULT_EDITABLE;  
      
    private DisplayMetrics metrics;  
      
      
    private PointF mPreMovePointF = new PointF();  
    private PointF mCurMovePointF = new PointF();  
      
    /** 
     * 圖片在旋轉時x方向的偏移量 
     */  
    private int offsetX;  
    /** 
     * 圖片在旋轉時y方向的偏移量 
     */  
    private int offsetY;  
      
    /** 
     * 控制圖示所在的位置(比如左上,右上,左下,右下) 
     */  
    private int controlLocation = DEFAULT_CONTROL_LOCATION;  
  
      
    public SingleTouchView(Context context, AttributeSet attrs) {  
        this(context, attrs, 0);  
    }  
  
    public SingleTouchView(Context context) {  
        this(context, null);  
    }  
  
    public SingleTouchView(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
        obtainStyledAttributes(attrs);  
        init();  
    }  
      
    /** 
     * 獲取自定義屬性 
     * @param attrs 
     */  
    private void obtainStyledAttributes(AttributeSet attrs){  
        metrics = getContext().getResources().getDisplayMetrics();  
        framePadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_FRAME_PADDING, metrics);  
        frameWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_FRAME_WIDTH, metrics);  
          
        TypedArray mTypedArray = getContext().obtainStyledAttributes(attrs,  
                R.styleable.SingleTouchView);  
          
//        Drawable srcDrawble = mTypedArray.getDrawable(R.styleable.SingleTouchView_src); 
        Drawable srcDrawble = getContext().getResources().getDrawable(R.drawable.back1); 
        mBitmap = drawable2Bitmap(srcDrawble);  
          
        framePadding = mTypedArray.getDimensionPixelSize(R.styleable.SingleTouchView_framePadding, framePadding);  
        frameWidth = mTypedArray.getDimensionPixelSize(R.styleable.SingleTouchView_frameWidth, frameWidth);  
        frameColor = mTypedArray.getColor(R.styleable.SingleTouchView_frameColor, DEFAULT_FRAME_COLOR);  
        mScale = mTypedArray.getFloat(R.styleable.SingleTouchView_scale, DEFAULT_SCALE);  
        mDegree = mTypedArray.getFloat(R.styleable.SingleTouchView_degree, DEFAULT_DEGREE);  
        controlDrawable = mTypedArray.getDrawable(R.styleable.SingleTouchView_controlDrawable);  
        controlLocation = mTypedArray.getInt(R.styleable.SingleTouchView_controlLocation, DEFAULT_CONTROL_LOCATION);  
        isEditable = mTypedArray.getBoolean(R.styleable.SingleTouchView_editable, DEFAULT_EDITABLE);  
          
        mTypedArray.recycle();  
          
    }  
      
      
    private void init(){  
        mPaint = new Paint();  
        mPaint.setAntiAlias(true);  
        mPaint.setColor(frameColor);  
        mPaint.setStrokeWidth(frameWidth);  
        mPaint.setStyle(Style.STROKE);  
          
        if(controlDrawable == null){  
            controlDrawable = getContext().getResources().getDrawable(R.drawable.ic_launcher);  
        }  
          
        mDrawableWidth = controlDrawable.getIntrinsicWidth();  
        mDrawableHeight = controlDrawable.getIntrinsicHeight();  
          
        transformDraw();   
    }  
      
      
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
          
        //獲取SingleTouchView所在父佈局的中心點  
        ViewGroup mViewGroup = (ViewGroup) getParent();  
        if(null != mViewGroup){  
            int parentWidth = mViewGroup.getWidth();  
            int parentHeight = mViewGroup.getHeight();  
            mCenterPoint.set(parentWidth/2, parentHeight/2);  
        }  
    }  
      
      
    /** 
     * 調整View的大小,位置 
     */  
    private void adjustLayout(){  
        int actualWidth = mViewWidth + mDrawableWidth;  
        int actualHeight = mViewHeight + mDrawableHeight;  
          
        int newPaddingLeft = (int) (mCenterPoint.x - actualWidth /2);  
        int newPaddingTop = (int) (mCenterPoint.y - actualHeight/2);  
          
        if(mViewPaddingLeft != newPaddingLeft || mViewPaddingTop != newPaddingTop){  
            mViewPaddingLeft = newPaddingLeft;  
            mViewPaddingTop = newPaddingTop;  
              
//          layout(newPaddingLeft, newPaddingTop, newPaddingLeft + actualWidth, newPaddingTop + actualHeight);  
        }  
          
        layout(newPaddingLeft, newPaddingTop, newPaddingLeft + actualWidth, newPaddingTop + actualHeight);  
    }  
      
      
    /** 
     * 設定旋轉圖 
     * @param bitmap 
     */  
    public void setImageBitamp(Bitmap bitmap){  
        this.mBitmap = bitmap;  
        transformDraw();  
    }  
      
      
    /** 
     * 設定旋轉圖 
     * @param drawable 
     */  
    public void setImageDrawable(Drawable drawable){  
        this.mBitmap = drawable2Bitmap(drawable);  
        transformDraw();  
    }  
      
    /** 
     * 從Drawable中獲取Bitmap物件 
     * @param drawable 
     * @return 
     */  
    private Bitmap drawable2Bitmap(Drawable drawable) {  
        try {  
            if (drawable == null) {  
                return null;  
            }  
  
//            if (drawable instanceof BitmapDrawable) {  
//                return ((BitmapDrawable)drawable).getBitmap();  
//            }  
  
            int intrinsicWidth = drawable.getIntrinsicWidth();  
            int intrinsicHeight = drawable.getIntrinsicHeight();  
            Bitmap bitmap = Bitmap.createBitmap(  
                    intrinsicWidth <= 0 ? DEFAULT_OTHER_DRAWABLE_WIDTH  
                            : intrinsicWidth,  
                    intrinsicHeight <= 0 ? DEFAULT_OTHER_DRAWABLE_HEIGHT  
                            : intrinsicHeight, Config.ARGB_8888);  
  
            Canvas canvas = new Canvas(bitmap);  
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());  
            drawable.draw(canvas);  
            return bitmap;  
        } catch (OutOfMemoryError e) {  
            return null;  
        }  
  
    }  
      
    /** 
     * 根據id設定旋轉圖 
     * @param resId 
     */  
    public void setImageResource(int resId){  
        Drawable drawable = getContext().getResources().getDrawable(resId);  
        setImageDrawable(drawable);  
    }  
      
    @Override  
    protected void onDraw(Canvas canvas) {  
        //每次draw之前調整View的位置和大小  
        super.onDraw(canvas);  
          
        if(mBitmap == null) return;  
        canvas.drawBitmap(mBitmap, matrix, mPaint);  
          
          
        //處於可編輯狀態才畫邊框和控制圖示  
        if(isEditable){  
            mPath.reset();  
            mPath.moveTo(mLTPoint.x, mLTPoint.y);  
            mPath.lineTo(mRTPoint.x, mRTPoint.y);  
            mPath.lineTo(mRBPoint.x, mRBPoint.y);  
            mPath.lineTo(mLBPoint.x, mLBPoint.y);  
            mPath.lineTo(mLTPoint.x, mLTPoint.y);  
            mPath.lineTo(mRTPoint.x, mRTPoint.y);  
            canvas.drawPath(mPath, mPaint);  
            //畫旋轉, 縮放圖示  
              
            controlDrawable.setBounds(mControlPoint.x - mDrawableWidth / 2,  
                    mControlPoint.y - mDrawableHeight / 2, mControlPoint.x + mDrawableWidth  
                            / 2, mControlPoint.y + mDrawableHeight / 2);  
            controlDrawable.draw(canvas);  
        }  
          
        adjustLayout();  
          
          
    }  
      
      
      
    /** 
     * 設定Matrix, 強制重新整理 
     */  
    private void transformDraw(){  
        if(mBitmap == null) return;  
        int bitmapWidth = (int)(mBitmap.getWidth() * mScale);  
        int bitmapHeight = (int)(mBitmap.getHeight()* mScale);  
        computeRect(-framePadding, -framePadding, bitmapWidth + framePadding, bitmapHeight + framePadding, mDegree);  
          
        //設定縮放比例  
        matrix.setScale(mScale, mScale);  
        //繞著圖片中心進行旋轉  
        matrix.postRotate(mDegree % 360, bitmapWidth/2, bitmapHeight/2);  
        //設定畫該圖片的起始點  
        matrix.postTranslate(offsetX + mDrawableWidth/2, offsetY + mDrawableHeight/2);  
          
        adjustLayout();  
    }  
      
      
    public boolean onTouchEvent(MotionEvent event) {  
        if(!isEditable){  
            return super.onTouchEvent(event);  
        }  
        switch (event.getAction() ) {  
        case MotionEvent.ACTION_DOWN:  
            mPreMovePointF.set(event.getX() + mViewPaddingLeft, event.getY() + mViewPaddingTop);  
              
            mStatus = JudgeStatus(event.getX(), event.getY());  
  
            break;  
        case MotionEvent.ACTION_UP:  
            mStatus = STATUS_INIT;  
            break;  
        case MotionEvent.ACTION_MOVE:  
            mCurMovePointF.set(event.getX() + mViewPaddingLeft, event.getY() + mViewPaddingTop);  
            if (mStatus == STATUS_ROTATE_ZOOM) {  
                float scale = 1f;  
                  
                int halfBitmapWidth = mBitmap.getWidth() / 2;  
                int halfBitmapHeight = mBitmap.getHeight() /2 ;  
                  
                //圖片某個點到圖片中心的距離  
                float bitmapToCenterDistance = FloatMath.sqrt(halfBitmapWidth * halfBitmapWidth + halfBitmapHeight * halfBitmapHeight);  
                  
                //移動的點到圖片中心的距離  
                float moveToCenterDistance = distance4PointF(mCenterPoint, mCurMovePointF);  
                  
                //計算縮放比例  
                scale = moveToCenterDistance / bitmapToCenterDistance;  
                  
                  
                //縮放比例的界限判斷  
                if (scale <= MIN_SCALE) {  
                    scale = MIN_SCALE;  
                } else if (scale >= MAX_SCALE) {  
                    scale = MAX_SCALE;  
                }  
                  
                  
                // 角度  
                double a = distance4PointF(mCenterPoint, mPreMovePointF);  
                double b = distance4PointF(mPreMovePointF, mCurMovePointF);  
                double c = distance4PointF(mCenterPoint, mCurMovePointF);  
                  
                double cosb = (a * a + c * c - b * b) / (2 * a * c);  
                  
                if (cosb >= 1) {  
                    cosb = 1f;  
                }  
                  
                double radian = Math.acos(cosb);  
                float newDegree = (float) radianToDegree(radian);  
                  
                //center -> proMove的向量, 我們使用PointF來實現  
                PointF centerToProMove = new PointF((mPreMovePointF.x - mCenterPoint.x), (mPreMovePointF.y - mCenterPoint.y));  
                  
                //center -> curMove 的向量    
                PointF centerToCurMove = new PointF((mCurMovePointF.x - mCenterPoint.x), (mCurMovePointF.y - mCenterPoint.y));  
                  
                //向量叉乘結果, 如果結果為負數, 表示為逆時針, 結果為正數表示順時針  
                float result = centerToProMove.x * centerToCurMove.y - centerToProMove.y * centerToCurMove.x;  
  
                if (result < 0) {  
                    newDegree = -newDegree;  
                }   
                  
                mDegree = mDegree + newDegree;  
                mScale = scale;  
                  
                transformDraw();  
            }  
            else if (mStatus == STATUS_DRAG) {  
                // 修改中心點  
                mCenterPoint.x += mCurMovePointF.x - mPreMovePointF.x;  
                mCenterPoint.y += mCurMovePointF.y - mPreMovePointF.y;  
                  
                System.out.println(this + "move = " + mCenterPoint);  
                  
                adjustLayout();  
            }  
              
            mPreMovePointF.set(mCurMovePointF);  
            break;  
        }  
        return true;  
    }  
      
      
      
    /** 
     * 獲取四個點和View的大小 
     * @param left 
     * @param top 
     * @param right 
     * @param bottom 
     * @param degree 
     */  
    private void computeRect(int left, int top, int right, int bottom, float degree){  
        Point lt = new Point(left, top);  
        Point rt = new Point(right, top);  
        Point rb = new Point(right, bottom);  
        Point lb = new Point(left, bottom);  
        Point cp = new Point((left + right) / 2, (top + bottom) / 2);  
        mLTPoint = obtainRoationPoint(cp, lt, degree);  
        mRTPoint = obtainRoationPoint(cp, rt, degree);  
        mRBPoint = obtainRoationPoint(cp, rb, degree);  
        mLBPoint = obtainRoationPoint(cp, lb, degree);  
          
        //計算X座標最大的值和最小的值  
        int maxCoordinateX = getMaxValue(mLTPoint.x, mRTPoint.x, mRBPoint.x, mLBPoint.x);  
        int minCoordinateX = getMinValue(mLTPoint.x, mRTPoint.x, mRBPoint.x, mLBPoint.x);;  
          
        mViewWidth = maxCoordinateX - minCoordinateX ;  
          
          
        //計算Y座標最大的值和最小的值  
        int maxCoordinateY = getMaxValue(mLTPoint.y, mRTPoint.y, mRBPoint.y, mLBPoint.y);  
        int minCoordinateY = getMinValue(mLTPoint.y, mRTPoint.y, mRBPoint.y, mLBPoint.y);  
  
        mViewHeight = maxCoordinateY - minCoordinateY ;  
          
          
        //View中心點的座標  
        Point viewCenterPoint = new Point((maxCoordinateX + minCoordinateX) / 2, (maxCoordinateY + minCoordinateY) / 2);  
          
        offsetX = mViewWidth / 2 - viewCenterPoint.x;  
        offsetY = mViewHeight / 2 - viewCenterPoint.y;  
          
          
          
        int halfDrawableWidth = mDrawableWidth / 2;  
        int halfDrawableHeight = mDrawableHeight /2;  
          
        //將Bitmap的四個點的X的座標移動offsetX + halfDrawableWidth  
        mLTPoint.x += (offsetX + halfDrawableWidth);  
        mRTPoint.x += (offsetX + halfDrawableWidth);  
        mRBPoint.x += (offsetX + halfDrawableWidth);  
        mLBPoint.x += (offsetX + halfDrawableWidth);  
  
        //將Bitmap的四個點的Y座標移動offsetY + halfDrawableHeight  
        mLTPoint.y += (offsetY + halfDrawableHeight);  
        mRTPoint.y += (offsetY + halfDrawableHeight);  
        mRBPoint.y += (offsetY + halfDrawableHeight);  
        mLBPoint.y += (offsetY + halfDrawableHeight);  
          
        mControlPoint = LocationToPoint(controlLocation);  
    }  
      
      
    /** 
     * 根據位置判斷控制圖示處於那個點 
     * @return 
     */  
    private Point LocationToPoint(int location){  
        switch(location){  
        case LEFT_TOP:  
            return mLTPoint;  
        case RIGHT_TOP:  
            return mRTPoint;  
        case RIGHT_BOTTOM:  
            return mRBPoint;  
        case LEFT_BOTTOM:  
            return mLBPoint;  
        }  
        return mLTPoint;  
    }  
      
      
    /** 
     * 獲取變長引數最大的值 
     * @param array 
     * @return 
     */  
    public int getMaxValue(Integer...array){  
        List<Integer> list = Arrays.asList(array);  
        Collections.sort(list);  
        return list.get(list.size() -1);  
    }  
      
      
    /** 
     * 獲取變長引數最大的值 
     * @param array 
     * @return 
     */  
    public int getMinValue(Integer...array){  
        List<Integer> list = Arrays.asList(array);  
        Collections.sort(list);  
        return list.get(0);  
    }  
      
      
      
    /** 
     * 獲取旋轉某個角度之後的點 
     * @param viewCenter 
     * @param source 
     * @param degree 
     * @return 
     */  
    public static Point obtainRoationPoint(Point center, Point source, float degree) {  
        //兩者之間的距離  
        Point disPoint = new Point();  
        disPoint.x = source.x - center.x;  
        disPoint.y = source.y - center.y;  
          
        //沒旋轉之前的弧度  
        double originRadian = 0;  
  
        //沒旋轉之前的角度  
        double originDegree = 0;  
          
        //旋轉之後的角度  
        double resultDegree = 0;  
          
        //旋轉之後的弧度  
        double resultRadian = 0;  
          
        //經過旋轉之後點的座標  
        Point resultPoint = new Point();  
          
        double distance = Math.sqrt(disPoint.x * disPoint.x + disPoint.y * disPoint.y);  
        if (disPoint.x == 0 && disPoint.y == 0) {  
            return center;  
            // 第一象限  
        } else if (disPoint.x >= 0 && disPoint.y >= 0) {  
            // 計算與x正方向的夾角  
            originRadian = Math.asin(disPoint.y / distance);  
              
            // 第二象限  
        } else if (disPoint.x < 0 && disPoint.y >= 0) {  
            // 計算與x正方向的夾角  
            originRadian = Math.asin(Math.abs(disPoint.x) / distance);  
            originRadian = originRadian + Math.PI / 2;  
              
            // 第三象限  
        } else if (disPoint.x < 0 && disPoint.y < 0) {  
            // 計算與x正方向的夾角  
            originRadian = Math.asin(Math.abs(disPoint.y) / distance);  
            originRadian = originRadian + Math.PI;  
        } else if (disPoint.x >= 0 && disPoint.y < 0) {  
            // 計算與x正方向的夾角  
            originRadian = Math.asin(disPoint.x / distance);  
            originRadian = originRadian + Math.PI * 3 / 2;  
        }  
          
        // 弧度換算成角度  
        originDegree = radianToDegree(originRadian);  
        resultDegree = originDegree + degree;  
          
        // 角度轉弧度  
        resultRadian = degreeToRadian(resultDegree);  
          
        resultPoint.x = (int) Math.round(distance * Math.cos(resultRadian));  
        resultPoint.y = (int) Math.round(distance * Math.sin(resultRadian));  
        resultPoint.x += center.x;  
        resultPoint.y += center.y;  
  
        return resultPoint;  
    }  
  
    /** 
     * 弧度換算成角度 
     *  
     * @return 
     */  
    public static double radianToDegree(double radian) {  
        return radian * 180 / Math.PI;  
    }  
  
      
    /** 
     * 角度換算成弧度 
     * @param degree 
     * @return 
     */  
    public static double degreeToRadian(double degree) {  
        return degree * Math.PI / 180;  
    }  
      
    /** 
     * 根據點選的位置判斷是否點中控制旋轉,縮放的圖片, 初略的計算 
     * @param x 
     * @param y 
     * @return 
     */  
    private int JudgeStatus(float x, float y){  
        PointF touchPoint = new PointF(x, y);  
        PointF controlPointF = new PointF(mControlPoint);  
          
        //點選的點到控制旋轉,縮放點的距離  
        float distanceToControl = distance4PointF(touchPoint, controlPointF);  
          
        //如果兩者之間的距離小於 控制圖示的寬度,高度的最小值,則認為點中了控制圖示  
        if(distanceToControl < Math.min(mDrawableWidth/2, mDrawableHeight/2)){  
            return STATUS_ROTATE_ZOOM;  
        }  
          
        return STATUS_DRAG;  
          
    }  
      
      
    public float getImageDegree() {  
        return mDegree;  
    }  
  
    /** 
     * 設定圖片旋轉角度 
     * @param degree 
     */  
    public void setImageDegree(float degree) {  
        if(this.mDegree != degree){  
            this.mDegree = degree;  
            transformDraw();  
        }  
    }  
  
    public float getImageScale() {  
        return mScale;  
    }  
  
    /** 
     * 設定圖片縮放比例 
     * @param scale 
     */  
    public void setImageScale(float scale) {  
        if(this.mScale != scale){  
            this.mScale = scale;  
            transformDraw();  
        };  
    }  
      
  
    public Drawable getControlDrawable() {  
        return controlDrawable;  
    }  
  
    /** 
     * 設定控制圖示 
     * @param drawable 
     */  
    public void setControlDrawable(Drawable drawable) {  
        this.controlDrawable = drawable;  
        mDrawableWidth = drawable.getIntrinsicWidth();  
        mDrawableHeight = drawable.getIntrinsicHeight();  
        transformDraw();  
    }  
  
    public int getFramePadding() {  
        return framePadding;  
    }  
  
    public void setFramePadding(int framePadding) {  
        if(this.framePadding == framePadding)  
            return;  
        this.framePadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, framePadding, metrics);  
        transformDraw();  
    }  
  
    public int getFrameColor() {  
        return frameColor;  
    }  
  
    public void setFrameColor(int frameColor) {  
        if(this.frameColor == frameColor)  
            return;  
        this.frameColor = frameColor;  
        mPaint.setColor(frameColor);  
        invalidate();  
    }  
  
    public int getFrameWidth() {  
        return frameWidth;  
    }  
  
    public void setFrameWidth(int frameWidth) {  
        if(this.frameWidth == frameWidth)   
            return;  
        this.frameWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, frameWidth, metrics);  
        mPaint.setStrokeWidth(frameWidth);  
        invalidate();  
    }  
      
    /** 
     * 設定控制圖示的位置, 設定的值只能選擇LEFT_TOP ,RIGHT_TOP, RIGHT_BOTTOM,LEFT_BOTTOM 
     * @param controlLocation 
     */  
    public void setControlLocation(int location) {  
        if(this.controlLocation == location)  
            return;  
        this.controlLocation = location;  
        transformDraw();  
    }  
  
    public int getControlLocation() {  
        return controlLocation;  
    }  
      
      
  
    public PointF getCenterPoint() {  
        return mCenterPoint;  
    }  
  
    /** 
     * 設定圖片中心點位置,相對於父佈局而言 
     * @param mCenterPoint 
     */  
    public void setCenterPoint(PointF mCenterPoint) {  
        this.mCenterPoint = mCenterPoint;  
        adjustLayout();  
    }  
      
  
    public boolean isEditable() {  
        return isEditable;  
    }  
  
    /** 
     * 設定是否處於可縮放,平移,旋轉狀態 
     * @param isEditable 
     */  
    public void setEditable(boolean isEditable) {  
        this.isEditable = isEditable;  
        invalidate();  
    }  
  
    /** 
     * 兩個點之間的距離 
     * @param x1 
     * @param y1 
     * @param x2 
     * @param y2 
     * @return 
     */  
    private float distance4PointF(PointF pf1, PointF pf2) {  
        float disX = pf2.x - pf1.x;  
        float disY = pf2.y - pf1.y;  
        return FloatMath.sqrt(disX * disX + disY * disY);  
    }  
      
  

}  

///////////////////////////////////////////////////////////////////////////////////

佈局檔案

<?xml version="1.0" encoding="UTF-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools">  
    <!-- xmlns:app="http://schemas.android.com/apk/res-auto"   -->
  
        <com.app.freestyle.SingleTouchView 
            xmlns:app="http://schemas.android.com/apk/res/com.app.freestyle" 
            android:id="@+id/SingleTouchView"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            app:scale="1.2"  
            app:src="@drawable/back3"  
            app:frameColor="#0022ff"  
            app:controlLocation="right_top"/>  
  
</merge>  

///////////////////////////////////////////////////////////////////////

attrs.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<resources>


    <!-- LockPatternView class attributes -->
    <declare-styleable name="SingleTouchView">
        <attr name="src" format="reference" />            <!-- 用於縮放旋轉的圖示 --> 
        <attr name="framePadding" format="dimension" />
        <attr name="frameWidth" format="dimension" />
        <attr name="frameColor" format="color" />
        <attr name="scale" format="float" />
        <attr name="degree" format="float" />
        <attr name="controlDrawable" format="reference" />
        <attr name="editable" format="boolean" />
         <attr name="controlLocation">                     <!-- 控制圖示的位置 -->  
        <enum name="left_top" value="0" />  
        <enum name="right_top" value="1" />  
        <enum name="right_bottom" value="2" />  
        <enum name="left_bottom" value="3" />  
    </attr>  
    </declare-styleable>
   
</resources> 

相關推薦

ios-day02-03(使用transform按鈕進行平移旋轉)

// // LiuJieViewController.m // 03-transform // // Created by XinYou on 15-1-30. // Copyright (c) 2015年 vxinyou. All rights reserved. // #import "LiuJ

Android圖片進行平移旋轉操作

package com.app.freestyle; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.app.freestyle.R; i

Android自定義imageview可圖片進行多點和拖動

package com.msstudent.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import andro

自定義控制元件: android中手勢操作圖片平移旋轉 並儲存

package com.su.testscsleimage; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import andro

Android單點觸控技術圖片進行平移旋轉操作

相信大家使用多點對圖片進行縮放,平移的操作很熟悉了,大部分大圖的瀏覽都具有此功能,有些app還可以對圖片進行旋轉操作,QQ的大圖瀏覽就可以對圖片進行旋轉操作,大家都知道對圖片進行縮放,平移,旋轉等操作可以使用Matrix來實現,Matrix就是一個3X3的矩陣,對圖片的處理可

【轉】 Qt繪圖顯示圖片影象平移旋轉和扭曲圖片的方法 宣告:本

現在我們來實現在視窗上顯示圖片,並學習怎樣將圖片進行平移,縮放,旋轉和扭曲。這裡我們是利用QPixmap類來實現圖片顯示的。 一、利用QPixmap顯示圖片。 1.將以前的工程資料夾進行復製備份,我們這裡將工程資料夾改名為painter05。(以前已經說過,經常備

android 實現圖片旋轉移動並且記錄變化值用另外一張圖片顯示出來

最近公司要做一個戒指試戴的功能,就是把戒指通過手勢移動到你指定的手指處,並且儲存狀態,方便下次進入時顯示,可以參考APP“鑽石快線”的試戴功能, 圖片網上有很多的教程教你怎麼把圖片旋轉,移動,縮放,等等,卻沒有教你儲存狀態,而且網上的教程都亂七八糟,都是複製貼上,都不是自己

Android matrix偏移(平移)旋轉傾斜的原理

第一部分 Matrix的數學原理 在Android中,如果你用Matrix進行過影象處理,那麼一定知道Matrix這個類。Android中的Matrix是一個3 x 3的矩陣,其內容如下: Matrix的對影象的處理可分為四類基本變換: Translate   

屬性動畫實現透明旋轉平移集合動畫

佈局檔案,設定透明,旋轉,平移,縮放,集合動畫的按鈕,再設定一個屬性動畫的imageview <?xml version="1.0" encoding="utf-8"?> <ImageButton android:id="@+id/i

圖片按螢幕大小不能填充整個螢幕

如題,用createScaledBitmap想要調整到適應螢幕,可是在320*480上的適應螢幕沒問題,在480*800的就一直調不好 原因是忽略了螢幕密度的問題。 螢幕密度=getResource.getDisplayMetrics().density; bitmap

html5學習筆記三:canvas中平移旋轉等影象變換問題

1,儲存與恢復問題 關鍵字:save / restore save指儲存save之前的canvas狀態,restore恢復save儲存的canvas狀態。舉個例子我想在canvas中隔一秒顯示一個圖片,那我可以先用save指令儲存空白的canvas,然後在顯示一張圖片之後r

OpenCV2.4.13中warpAffine函式理解旋轉仿射變換保持完整圖片

本文借鑑了這裡以及這裡的內容。 問題:為什麼寫這個東西? 答:在進行模板匹配的時候,發現一個問題,對於直接從圖片中摳出的模板,匹配效果較好,但是當模板發生形變的時候,效果就不理想了。 在對模板進行形變處理的時候,發現利用 warpAffine得到的結果並不

IOS CGAffineTransform 用於檢視平移旋轉

今天碰到了一個旋轉放縮圖片的一個demo,在看的過程中發現實現圖片變化的那個方法特別簡單。一共只有三句話,下面就是這個方法- (void)transformImageView{CGAffineTransform t = CGAffineTransformMakeScale(

canvas之圖形的變化(儲存平移旋轉

1、儲存與恢復canvas狀態 ctx.save();暫時將當前的狀態儲存到堆中 ctx.restore();該方法用於將上一個儲存的狀態從堆中再次取出,恢復該狀態的所有設定。 <meta charset="utf-8"> <title><

Android 使用變形矩陣實現可以拖拽旋轉的影象

上篇博文介紹了變形矩陣的一些用法,所以這篇博文就結合變形矩陣來實現一個可以拖拽、縮放、旋轉的影象吧。 首先,我們就繼承ImageView來實現我們的自定義View。 程式碼如下: public class MyMatrixImg extends Ima

Android拖動自定義內容控制元件製作(可拖動RelativeLayout定製)

先上效果圖: 一.     製作此控制元件的起源 專案需要一個可以拖動的控制元件,在網上可以找到很多例子,有圖片拖動控制元件,有textview拖動控制元件。但是專案中需要控制元件同時可以動態通過手指調整尺寸,並且控制元件的內容不固定,需要自定義內容,即可以新增任意內容

基本動畫、復合動畫設置 平移旋轉、透明度 編碼實現 xml實現

sca ons new rpo 頂點 進行 clas imageview abs public class VAActivity extends Activity { private ImageView iv_animation; private Tex

影象處理之影象基本變化(平移旋轉)(Octave實現)

在模式識別及計算機視覺中,要經常進行影象的變化。 例如:在識別手寫數字中,我們可能在廣泛應用中要求所有的圖片都是20*20這麼好的規格。所以,我們就需要進行縮放來達到目的。 今天來總結下學到的影象的基本變換。 首先我們計 (w,v) (w,v)為源影象的

css3實現顏色漸變、元素的2D轉換(元素的旋轉移動傾斜等)、元素轉換過渡效果

一、顏色漸變:background: linear-gradient(direction, color-stop1, color-stop2, ...); 引數:direction: 方向或者角度;  color-stop1, color-stop2, ... :指定漸變的

原生webgl學習(八) WebGL實現動畫:平移旋轉

筆者在前面的文章主要是針對二維的靜態圖形進行開發;但有時候我們需要模型動起來,就像真實世界中的一切運動變化一樣。場景如果不是動態的,那麼可想而知,我們的世界是多麼枯燥乏味。為了讓我們開發的圖形應用看上去更加高大上,這一節筆者將和大家一起做一個動畫的例子;本節的內容用到了前面文