android Matrix圖片隨意的放大縮小,拖動

step1:新建一個項目DragAndZoom,並準備一張照片放在res/drawable-hdpi目錄下,如下圖所示:

       

step2: 設置應用的UI界面,在main.xml中設置:

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ImageView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:src="@drawable/wall"  
  11.     android:id="@+id/imageView"  
  12.     android:scaleType="matrix"     
  13.     />  <!-- 指定爲matrix類型 -->  
  14. </LinearLayout>  

step3:MainActivity.java中實現具體的需求

[java] view plain copy
  1. package cn.roco.drag;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Matrix;  
  5. import android.graphics.PointF;  
  6. import android.os.Bundle;  
  7. import android.util.FloatMath;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnTouchListener;  
  11. import android.widget.ImageView;  
  12.   
  13. public class MainActivity extends Activity {  
  14.   
  15.     private ImageView imageView;  
  16.   
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.   
  22.         imageView = (ImageView) this.findViewById(R.id.imageView);  
  23.         imageView.setOnTouchListener(new TouchListener());  
  24.     }  
  25.   
  26.     private final class TouchListener implements OnTouchListener {  
  27.           
  28.         /** 記錄是拖拉照片模式還是放大縮小照片模式 */  
  29.         private int mode = 0;// 初始狀態    
  30.         /** 拖拉照片模式 */  
  31.         private static final int MODE_DRAG = 1;  
  32.         /** 放大縮小照片模式 */  
  33.         private static final int MODE_ZOOM = 2;  
  34.           
  35.         /** 用於記錄開始時候的座標位置 */  
  36.         private PointF startPoint = new PointF();  
  37.         /** 用於記錄拖拉圖片移動的座標位置 */  
  38.         private Matrix matrix = new Matrix();  
  39.         /** 用於記錄圖片要進行拖拉時候的座標位置 */  
  40.         private Matrix currentMatrix = new Matrix();  
  41.       
  42.         /** 兩個手指的開始距離 */  
  43.         private float startDis;  
  44.         /** 兩個手指的中間點 */  
  45.         private PointF midPoint;  
  46.   
  47.         @Override  
  48.         public boolean onTouch(View v, MotionEvent event) {  
  49.             /** 通過與運算保留最後八位 MotionEvent.ACTION_MASK = 255 */  
  50.             switch (event.getAction() & MotionEvent.ACTION_MASK) {  
  51.             // 手指壓下屏幕  
  52.             case MotionEvent.ACTION_DOWN:  
  53.                 mode = MODE_DRAG;  
  54.                 // 記錄ImageView當前的移動位置  
  55.                 currentMatrix.set(imageView.getImageMatrix());  
  56.                 startPoint.set(event.getX(), event.getY());  
  57.                 break;  
  58.             // 手指在屏幕上移動,改事件會被不斷觸發  
  59.             case MotionEvent.ACTION_MOVE:  
  60.                 // 拖拉圖片  
  61.                 if (mode == MODE_DRAG) {  
  62.                     float dx = event.getX() - startPoint.x; // 得到x軸的移動距離  
  63.                     float dy = event.getY() - startPoint.y; // 得到x軸的移動距離  
  64.                     // 在沒有移動之前的位置上進行移動  
  65.                     matrix.set(currentMatrix);  
  66.                     matrix.postTranslate(dx, dy);  
  67.                 }  
  68.                 // 放大縮小圖片  
  69.                 else if (mode == MODE_ZOOM) {  
  70.                     float endDis = distance(event);// 結束距離  
  71.                     if (endDis > 10f) { // 兩個手指併攏在一起的時候像素大於10  
  72.                         float scale = endDis / startDis;// 得到縮放倍數  
  73.                         matrix.set(currentMatrix);  
  74.                         matrix.postScale(scale, scale,midPoint.x,midPoint.y);  
  75.                     }  
  76.                 }  
  77.                 break;  
  78.             // 手指離開屏幕  
  79.             case MotionEvent.ACTION_UP:  
  80.                 // 當觸點離開屏幕,但是屏幕上還有觸點(手指)  
  81.             case MotionEvent.ACTION_POINTER_UP:  
  82.                 mode = 0;  
  83.                 break;  
  84.             // 當屏幕上已經有觸點(手指),再有一個觸點壓下屏幕  
  85.             case MotionEvent.ACTION_POINTER_DOWN:  
  86.                 mode = MODE_ZOOM;  
  87.                 /** 計算兩個手指間的距離 */  
  88.                 startDis = distance(event);  
  89.                 /** 計算兩個手指間的中間點 */  
  90.                 if (startDis > 10f) { // 兩個手指併攏在一起的時候像素大於10  
  91.                     midPoint = mid(event);  
  92.                     //記錄當前ImageView的縮放倍數  
  93.                     currentMatrix.set(imageView.getImageMatrix());  
  94.                 }  
  95.                 break;  
  96.             }  
  97.             imageView.setImageMatrix(matrix);  
  98.             return true;  
  99.         }  
  100.   
  101.         /** 計算兩個手指間的距離 */  
  102.         private float distance(MotionEvent event) {  
  103.             float dx = event.getX(1) - event.getX(0);  
  104.             float dy = event.getY(1) - event.getY(0);  
  105.             /** 使用勾股定理返回兩點之間的距離 */  
  106.             return FloatMath.sqrt(dx * dx + dy * dy);  
  107.         }  
  108.   
  109.         /** 計算兩個手指間的中間點 */  
  110.         private PointF mid(MotionEvent event) {  
  111.             float midX = (event.getX(1) + event.getX(0)) / 2;  
  112.             float midY = (event.getY(1) + event.getY(0)) / 2;  
  113.             return new PointF(midX, midY);  
  114.         }  
  115.   
  116.     }  
  117.   
  118. }  

step4:AndroidMainfest.xml

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="cn.roco.drag"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="8" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".MainActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>  

step5:具體的效果圖

                               

上面兩個是圖片拖拽的效果,而圖片的縮放效果要在真機中才能夠看得到,請讀者自己在真機環境中測試。


附註:具體的程序源碼在:http://pan.baidu.com/share/link?shareid=397888&uk=805959799





其實 通過通過手勢也可以縮放圖片    左--->右 放大 右 --->左 縮小 速度越快,縮放比例越大

zoom.xml

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ImageView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:src="@drawable/wall"  
  11.     android:id="@+id/show"  
  12.     android:scaleType="matrix"     
  13.     />  <!-- 指定爲matrix類型 -->  
  14. </LinearLayout>  

GestureZoom.java

[java] view plain copy
  1. package cn.roco.gesture;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Matrix;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.os.Bundle;  
  9. import android.view.GestureDetector;  
  10. import android.view.GestureDetector.OnGestureListener;  
  11. import android.view.MotionEvent;  
  12. import android.widget.ImageView;  
  13.   
  14. /** 
  15.  * 通過手勢 縮放圖片 左--->右 放大 右 --->左 縮小 速度越快,縮放比例越大 
  16.  */  
  17. public class GestureZoom extends Activity implements OnGestureListener {  
  18.     // 定義手勢檢測器實例  
  19.     GestureDetector detector;  
  20.     ImageView imageView;  
  21.     // 初始化圖片資源  
  22.     Bitmap bitmap;  
  23.     // 定義圖片的高和寬  
  24.     int width, height;  
  25.     // 記錄當前的縮放比  
  26.     float currentScale = 1;  
  27.     // 控制圖片縮放的Matrix對象  
  28.     Matrix matrix;  
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.zoom);  
  34.         // 創建手勢檢測器  
  35.         detector = new GestureDetector(this);  
  36.         imageView = (ImageView) findViewById(R.id.show);  
  37.         matrix = new Matrix();  
  38.         // 獲取被縮放的源圖片  
  39.         bitmap = BitmapFactory.decodeResource(this.getResources(),  
  40.                 R.drawable.wall);  
  41.         // 獲得位圖的寬  
  42.         width = bitmap.getWidth();  
  43.         // 獲得位圖的高  
  44.         height = bitmap.getHeight();  
  45.         // 設置 ImageView初始化顯示的圖片  
  46.         imageView.setImageBitmap(BitmapFactory.decodeResource(  
  47.                 this.getResources(), R.drawable.wall));  
  48.     }  
  49.   
  50.     @Override  
  51.     public boolean onTouchEvent(MotionEvent event) {  
  52.         // 將該Activity上的觸碰時間交個 GestureDetector處理  
  53.         return detector.onTouchEvent(event);  
  54.     }  
  55.   
  56.     @Override  
  57.     public boolean onDown(MotionEvent e) {  
  58.         // TODO Auto-generated method stub  
  59.         return false;  
  60.     }  
  61.   
  62.     @Override  
  63.     public void onShowPress(MotionEvent e) {  
  64.         // TODO Auto-generated method stub  
  65.   
  66.     }  
  67.   
  68.     @Override  
  69.     public boolean onSingleTapUp(MotionEvent e) {  
  70.         return false;  
  71.     }  
  72.   
  73.     @Override  
  74.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,  
  75.             float distanceY) {  
  76.         return false;  
  77.     }  
  78.   
  79.     @Override  
  80.     public void onLongPress(MotionEvent e) {  
  81.   
  82.     }  
  83.   
  84.     @Override  
  85.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  86.             float velocityY) {  
  87.         velocityX = velocityX > 4000 ? 4000 : velocityX;  
  88.         velocityY = velocityY < -4000 ? -4000 : velocityY;  
  89.         // 感覺手勢的速度來計算縮放比,如果 velocityX>0,放大圖像,否則縮小圖像  
  90.         currentScale += currentScale * velocityX / 4000.0f;  
  91.         // 保證 currentScale 不會等於0  
  92.         currentScale = currentScale > 0.01 ? currentScale : 0.01f;  
  93.         // 重置 Matrix  
  94.         matrix.setScale(currentScale, currentScale, 160200);  
  95.         BitmapDrawable tmp = (BitmapDrawable) imageView.getDrawable();  
  96.         // 如果圖片還未回收,先強制收回該圖片  
  97.         if (!tmp.getBitmap().isRecycled()) {  
  98.             tmp.getBitmap().recycle();  
  99.         }  
  100.         // 根據原始位圖和 Matrix創建新圖片  
  101.         Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 00, width, height,  
  102.                 matrix, true);  
  103.         //顯示新的位圖  
  104.         imageView.setImageBitmap(bitmap2);  
  105.         return true;  
  106.     }  
  107.       
  108. }  

查看一下運行的效果

                                                                          




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章