android中手勢操作圖片的平移、縮放、旋轉

在網上搜到很多都是一樣的版本,隻有平移和縮放的功能。我在搜到的源代碼基礎上添加瞭旋轉和邊界檢查的功能。

 代碼主要分兩部分,一個activity一個view,代碼如下:

[java] 
package com.example.touch; 
 
import android.app.Activity; 
import android.os.Bundle; 
 
public class TouchImageViewActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        TouchImageView img = new TouchImageView(this); 
        setContentView(img); 
    } 

[java] 
package com.example.touch; 
 
import android.graphics.Bitmap; 
import android.graphics.Bitmap.Config; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.PointF; 
import android.util.DisplayMetrics; 
import android.util.FloatMath; 
import android.view.MotionEvent; 
import android.widget.ImageView; 
 
public class TouchImageView extends ImageView { 
 
    float x_down = 0; 
    float y_down = 0; 
    PointF start = new PointF(); 
    PointF mid = new PointF(); 
    float oldDist = 1f; 
    float oldRotation = 0; 
    Matrix matrix = new Matrix(); 
    Matrix matrix1 = new Matrix(); 
    Matrix savedMatrix = new Matrix(); 
 
    private static final int NONE = 0; 
    private static final int DRAG = 1; 
    private static final int ZOOM = 2; 
    int mode = NONE; 
 
    boolean matrixCheck = false; 
 
    int widthScreen; 
    int heightScreen; 
 
    Bitmap gintama; 
 
    public TouchImageView(TouchImageViewActivity activity) { 
        super(activity); 
        gintama = BitmapFactory.decodeResource(getResources(), R.drawable.gintama); 
 
        DisplayMetrics dm = new DisplayMetrics(); 
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm); 
        widthScreen = dm.widthPixels; 
        heightScreen = dm.heightPixels; 
 
        matrix = new Matrix(); 
    } 
 
    protected void onDraw(Canvas canvas) { 
        canvas.save(); 
        canvas.drawBitmap(gintama, matrix, null); 
        canvas.restore(); 
    } 
 
    public boolean onTouchEvent(MotionEvent event) { 
        switch (event.getAction() & MotionEvent.ACTION_MASK) { 
        case MotionEvent.ACTION_DOWN: 
            mode = DRAG; 
            x_down = event.getX(); 
            y_down = event.getY(); 
            savedMatrix.set(matrix); 
            break; 
        case MotionEvent.ACTION_POINTER_DOWN: 
            mode = ZOOM; 
            oldDist = spacing(event); 
            oldRotation = rotation(event); 
            savedMatrix.set(matrix); 
            midPoint(mid, event); 
            break; 
        case MotionEvent.ACTION_MOVE: 
            if (mode == ZOOM) { 
                matrix1.set(savedMatrix); 
                float rotation = rotation(event) – oldRotation; 
                float newDist = spacing(event); 
                float scale = newDist / oldDist; 
                matrix1.postScale(scale, scale, mid.x, mid.y);// 縮放 
                matrix1.postRotate(rotation, mid.x, mid.y);// 旋轉 
                matrixCheck = matrixCheck(); 
                if (matrixCheck == false) { 
                    matrix.set(matrix1); 
                    invalidate(); 
                } 
            } else if (mode == DRAG) { 
                matrix1.set(savedMatrix); 
                matrix1.postTranslate(event.getX() – x_down, event.getY() 
                        – y_down);// 平移 
                matrixCheck = matrixCheck(); 
                matrixCheck = matrixCheck(); 
                if (matrixCheck == false) { 
                    matrix.set(matrix1); 
                    invalidate(); 
                } 
            } 
            break; 
        case MotionEvent.ACTION_UP: 
        case MotionEvent.ACTION_POINTER_UP: 
            mode = NONE; 
            break; 
        } 
        return true; 
    } 
 
    private boolean matrixCheck() { 
        float[] f = new float[9]; 
        matrix1.getValues(f); 
        // 圖片4個頂點的坐標 
        float x1 = f[0] * 0 + f[1] * 0 + f[2]; 
        float y1 = f[3] * 0 + f[4] * 0 + f[5]; 
        float x2 = f[0] * gintama.getWidth() + f[1] * 0 + f[2]; 
        float y2 = f[3] * gintama.getWidth() + f[4] * 0 + f[5]; 
        float x3 = f[0] * 0 + f[1] * gintama.getHeight() + f[2]; 
        float y3 = f[3] * 0 + f[4] * gintama.getHeight() + f[5]; 
        float x4 = f[0] * gintama.getWidth() + f[1] * gintama.getHeight() + f[2]; 
        float y4 = f[3] * gintama.getWidth() + f[4] * gintama.getHeight() + f[5]; 
        // 圖片現寬度 
        double width = Math.sqrt((x1 – x2) * (x1 – x2) + (y1 – y2) * (y1 – y2)); 
        // 縮放比率判斷 
        if (width < widthScreen / 3 || width > widthScreen * 3) { 
            return true; 
        } 
        // 出界判斷 
        if ((x1 < widthScreen / 3 && x2 < widthScreen / 3 
                && x3 < widthScreen / 3 && x4 < widthScreen / 3) 
                || (x1 > widthScreen * 2 / 3 && x2 > widthScreen * 2 / 3 
                        && x3 > widthScreen * 2 / 3 && x4 > widthScreen * 2 / 3) 
                || (y1 < heightScreen / 3 && y2 < heightScreen / 3 
                        && y3 < heightScreen / 3 && y4 < heightScreen / 3) 
                || (y1 > heightScreen * 2 / 3 && y2 > heightScreen * 2 / 3 
                        && y3 > heightScreen * 2 / 3 && y4 > heightScreen * 2 / 3)) { 
            return true; 
        } 
        return false; 
    } 
 
    // 觸碰兩點間距離 
    private float spacing(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 void midPoint(PointF point, MotionEvent event) { 
        float x = event.getX(0) + event.getX(1); 
        float y = event.getY(0) + event.getY(1); 
        point.set(x / 2, y / 2); 
    } 
 
    // 取旋轉角度 
    private float rotation(MotionEvent event) { 
        double delta_x = (event.getX(0) – event.getX(1)); 
        double delta_y = (event.getY(0) – event.getY(1)); 
        double radians = Math.atan2(delta_y, delta_x); 
        return (float) Math.toDegrees(radians); 
    } 
 
    // 將移動,縮放以及旋轉後的圖層保存為新圖片 
    // 本例中沒有用到該方法,需要保存圖片的可以參考 
    public Bitmap CreatNewPhoto() { 
        Bitmap bitmap = Bitmap.createBitmap(widthScreen, heightScreen, 
                Config.ARGB_8888); // 背景圖片 
        Canvas canvas = new Canvas(bitmap); // 新建畫佈 
        canvas.drawBitmap(gintama, matrix, null); // 畫圖片 
        canvas.save(Canvas.ALL_SAVE_FLAG); // 保存畫佈 
        canvas.restore(); 
        return bitmap; 
    } 
 

發佈留言