Android 可平移,縮放,旋轉的ImageView

yangxi_001發表於2014-08-11

在網上搜到很多都是一樣的版本,只有平移和縮放的功能。我在搜到的原始碼基礎上新增了旋轉和邊界檢查的功能。

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

[java] view plaincopy
  1. package com.example.touch;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class TouchImageViewActivity extends Activity {  
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         TouchImageView img = new TouchImageView(this);  
  12.         setContentView(img);  
  13.     }  
  14. }  

[java] view plaincopy
  1. package com.example.touch;  
  2.   
  3. import android.graphics.Bitmap;  
  4. import android.graphics.Bitmap.Config;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.Matrix;  
  8. import android.graphics.PointF;  
  9. import android.util.DisplayMetrics;  
  10. import android.util.FloatMath;  
  11. import android.view.MotionEvent;  
  12. import android.widget.ImageView;  
  13.   
  14. public class TouchImageView extends ImageView {  
  15.   
  16.     float x_down = 0;  
  17.     float y_down = 0;  
  18.     PointF start = new PointF();  
  19.     PointF mid = new PointF();  
  20.     float oldDist = 1f;  
  21.     float oldRotation = 0;  
  22.     Matrix matrix = new Matrix();  
  23.     Matrix matrix1 = new Matrix();  
  24.     Matrix savedMatrix = new Matrix();  
  25.   
  26.     private static final int NONE = 0;  
  27.     private static final int DRAG = 1;  
  28.     private static final int ZOOM = 2;  
  29.     int mode = NONE;  
  30.   
  31.     boolean matrixCheck = false;  
  32.   
  33.     int widthScreen;  
  34.     int heightScreen;  
  35.   
  36.     Bitmap gintama;  
  37.   
  38.     public TouchImageView(TouchImageViewActivity activity) {  
  39.         super(activity);  
  40.         gintama = BitmapFactory.decodeResource(getResources(), R.drawable.gintama);  
  41.   
  42.         DisplayMetrics dm = new DisplayMetrics();  
  43.         activity.getWindowManager().getDefaultDisplay().getMetrics(dm);  
  44.         widthScreen = dm.widthPixels;  
  45.         heightScreen = dm.heightPixels;  
  46.   
  47.         matrix = new Matrix();  
  48.     }  
  49.   
  50.     protected void onDraw(Canvas canvas) {  
  51.         canvas.save();  
  52.         canvas.drawBitmap(gintama, matrix, null);  
  53.         canvas.restore();  
  54.     }  
  55.   
  56.     public boolean onTouchEvent(MotionEvent event) {  
  57.         switch (event.getAction() & MotionEvent.ACTION_MASK) {  
  58.         case MotionEvent.ACTION_DOWN:  
  59.             mode = DRAG;  
  60.             x_down = event.getX();  
  61.             y_down = event.getY();  
  62.             savedMatrix.set(matrix);  
  63.             break;  
  64.         case MotionEvent.ACTION_POINTER_DOWN:  
  65.             mode = ZOOM;  
  66.             oldDist = spacing(event);  
  67.             oldRotation = rotation(event);  
  68.             savedMatrix.set(matrix);  
  69.             midPoint(mid, event);  
  70.             break;  
  71.         case MotionEvent.ACTION_MOVE:  
  72.             if (mode == ZOOM) {  
  73.                 matrix1.set(savedMatrix);  
  74.                 float rotation = rotation(event) - oldRotation;  
  75.                 float newDist = spacing(event);  
  76.                 float scale = newDist / oldDist;  
  77.                 matrix1.postScale(scale, scale, mid.x, mid.y);// 縮放  
  78.                 matrix1.postRotate(rotation, mid.x, mid.y);// 旋轉  
  79.                 matrixCheck = matrixCheck();  
  80.                 if (matrixCheck == false) {  
  81.                     matrix.set(matrix1);  
  82.                     invalidate();  
  83.                 }  
  84.             } else if (mode == DRAG) {  
  85.                 matrix1.set(savedMatrix);  
  86.                 matrix1.postTranslate(event.getX() - x_down, event.getY()  
  87.                         - y_down);// 平移  
  88.                 matrixCheck = matrixCheck();  
  89.                 matrixCheck = matrixCheck();  
  90.                 if (matrixCheck == false) {  
  91.                     matrix.set(matrix1);  
  92.                     invalidate();  
  93.                 }  
  94.             }  
  95.             break;  
  96.         case MotionEvent.ACTION_UP:  
  97.         case MotionEvent.ACTION_POINTER_UP:  
  98.             mode = NONE;  
  99.             break;  
  100.         }  
  101.         return true;  
  102.     }  
  103.   
  104.     private boolean matrixCheck() {  
  105.         float[] f = new float[9];  
  106.         matrix1.getValues(f);  
  107.         // 圖片4個頂點的座標  
  108.         float x1 = f[0] * 0 + f[1] * 0 + f[2];  
  109.         float y1 = f[3] * 0 + f[4] * 0 + f[5];  
  110.         float x2 = f[0] * gintama.getWidth() + f[1] * 0 + f[2];  
  111.         float y2 = f[3] * gintama.getWidth() + f[4] * 0 + f[5];  
  112.         float x3 = f[0] * 0 + f[1] * gintama.getHeight() + f[2];  
  113.         float y3 = f[3] * 0 + f[4] * gintama.getHeight() + f[5];  
  114.         float x4 = f[0] * gintama.getWidth() + f[1] * gintama.getHeight() + f[2];  
  115.         float y4 = f[3] * gintama.getWidth() + f[4] * gintama.getHeight() + f[5];  
  116.         // 圖片現寬度  
  117.         double width = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));  
  118.         // 縮放比率判斷  
  119.         if (width < widthScreen / 3 || width > widthScreen * 3) {  
  120.             return true;  
  121.         }  
  122.         // 出界判斷  
  123.         if ((x1 < widthScreen / 3 && x2 < widthScreen / 3  
  124.                 && x3 < widthScreen / 3 && x4 < widthScreen / 3)  
  125.                 || (x1 > widthScreen * 2 / 3 && x2 > widthScreen * 2 / 3  
  126.                         && x3 > widthScreen * 2 / 3 && x4 > widthScreen * 2 / 3)  
  127.                 || (y1 < heightScreen / 3 && y2 < heightScreen / 3  
  128.                         && y3 < heightScreen / 3 && y4 < heightScreen / 3)  
  129.                 || (y1 > heightScreen * 2 / 3 && y2 > heightScreen * 2 / 3  
  130.                         && y3 > heightScreen * 2 / 3 && y4 > heightScreen * 2 / 3)) {  
  131.             return true;  
  132.         }  
  133.         return false;  
  134.     }  
  135.   
  136.     // 觸碰兩點間距離  
  137.     private float spacing(MotionEvent event) {  
  138.         float x = event.getX(0) - event.getX(1);  
  139.         float y = event.getY(0) - event.getY(1);  
  140.         return FloatMath.sqrt(x * x + y * y);  
  141.     }  
  142.       
  143.     // 取手勢中心點  
  144.     private void midPoint(PointF point, MotionEvent event) {  
  145.         float x = event.getX(0) + event.getX(1);  
  146.         float y = event.getY(0) + event.getY(1);  
  147.         point.set(x / 2, y / 2);  
  148.     }  
  149.   
  150.     // 取旋轉角度  
  151.     private float rotation(MotionEvent event) {  
  152.         double delta_x = (event.getX(0) - event.getX(1));  
  153.         double delta_y = (event.getY(0) - event.getY(1));  
  154.         double radians = Math.atan2(delta_y, delta_x);  
  155.         return (float) Math.toDegrees(radians);  
  156.     }  
  157.   
  158.     // 將移動,縮放以及旋轉後的圖層儲存為新圖片  
  159.     // 本例中沒有用到該方法,需要儲存圖片的可以參考  
  160.     public Bitmap CreatNewPhoto() {  
  161.         Bitmap bitmap = Bitmap.createBitmap(widthScreen, heightScreen,  
  162.                 Config.ARGB_8888); // 背景圖片  
  163.         Canvas canvas = new Canvas(bitmap); // 新建畫布  
  164.         canvas.drawBitmap(gintama, matrix, null); // 畫圖片  
  165.         canvas.save(Canvas.ALL_SAVE_FLAG); // 儲存畫布  
  166.         canvas.restore();  
  167.         return bitmap;  
  168.     }  
  169.   
  170. }  

相關文章