android Matrix圖片的縮放和拖動

              開發中經常遇到圖片的大小超過手機屏幕的大小,或者圖片過小,在手機上顯示出來太小,這時候我們就需要對圖片進行放大縮小或者拖動。

         android爲ImageView提供了scaleType的屬性,在scaleType的屬性值有多種,大部分是根據高和寬經行縮放,但是無法動態的縮放,只有matrix是可以進行動態縮放的,所以我們在這之前有必要了解一下matrix屬性。

       Matrix主要用於對平面進行平移(Translate),縮放(Scale),旋轉(Rotate)以及斜切(Skew)操作。爲簡化矩陣變換,Android封裝了一系列方法來進行矩陣變換;其中包括:

set系列方法:setTranslate,setScale,setRotate,setSkew;設置,會覆蓋之前的參數。
pre系列方法:preTranslate,preScale,preRotate,preSkew;矩陣先乘,如M' = M * T(dx, dy)。
post系列方法:postTranslate,postScale,postRotate,postSkew;矩陣後乘,如M' = T(dx, dy) * M。
通過將變換矩陣與原始矩陣相乘來達到變換的目的。

       接下來我們回到正題。首先看效果圖:(有哪位大神知道真機上哪個App可以做gif圖,給推薦一下。現在只能給大家一張一張的上圖了,哈哈。。)

         圖片順序依次是  原圖——縮略圖——放大圖——拖動圖



    然後就是java代碼和xml佈局了

   先看一下xml佈局,其中android:scaleType="matrix" 非常重要。

<span style="color:#009900;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<ImageView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:src="@drawable/pic"
    android:id="@+id/imageView"
    android:scaleType="matrix"   
    />  
</LinearLayout></span>
   接下來就是java代碼了,首先說一下思路,無非就是根據手機屏幕的點擊事件(onTouch),根據手指在屏幕上的點擊,移動,擡起來計算手指的位移,根據位移來進行放大縮小或者拖動,詳細註釋都在代碼中標明,直接上代碼

<span style="color:#33cc00;">import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MainActivity extends Activity {  
	  
    private ImageView imageView;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
  
        imageView = (ImageView) this.findViewById(R.id.imageView);  
        imageView.setOnTouchListener(new TouchListener());  
    }  
  
    private final class TouchListener implements OnTouchListener {  
          
        /** 記錄是拖拉照片模式還是放大縮小照片模式 */  
        private int mode = 0;// 初始狀態    
        /** 拖拉照片模式 */  
        private static final int MODE_DRAG = 1;  
        /** 放大縮小照片模式 */  
        private static final int MODE_ZOOM = 2;  
          
        /** 用於記錄開始時候的座標位置 */  
        private PointF startPoint = new PointF();  
        /** 用於記錄拖拉圖片移動的座標位置 */  
        private Matrix matrix = new Matrix();  
        /** 用於記錄圖片要進行拖拉時候的座標位置 */  
        private Matrix currentMatrix = new Matrix();  
      
        /** 兩個手指的開始距離 */  
        private float startDis;  
        /** 兩個手指的中間點 */  
        private PointF midPoint;  
  
        /** 手指點擊屏幕的觸摸事件*/
        @Override  
        public boolean onTouch(View v, MotionEvent event) {  
            /** 通過與運算保留最後八位 MotionEvent.ACTION_MASK = 255 */  
            switch (event.getAction() & MotionEvent.ACTION_MASK) {  
            // 手指壓下屏幕  
            case MotionEvent.ACTION_DOWN:  
                mode = MODE_DRAG;  
                // 記錄ImageView當前的移動位置  
                currentMatrix.set(imageView.getImageMatrix());  
                startPoint.set(event.getX(), event.getY());  
                break;  
            // 手指在屏幕上移動,改事件會被不斷觸發  
            case MotionEvent.ACTION_MOVE:  
                // 拖拉圖片  
                if (mode == MODE_DRAG) {  
                    float dx = event.getX() - startPoint.x; // 得到x軸的移動距離  
                    float dy = event.getY() - startPoint.y; // 得到x軸的移動距離  
                    // 在沒有移動之前的位置上進行移動  
                    matrix.set(currentMatrix);  
                    matrix.postTranslate(dx, dy);  
                }  
                // 放大縮小圖片  
                else if (mode == MODE_ZOOM) {  
                    float endDis = distance(event);// 結束距離  
                    if (endDis > 10f) { // 兩個手指併攏在一起的時候像素大於10  
                        float scale = endDis / startDis;// 得到縮放倍數  
                        matrix.set(currentMatrix);  
                        matrix.postScale(scale, scale,midPoint.x,midPoint.y);  
                    }  
                }  
                break;  
            // 手指離開屏幕  
            case MotionEvent.ACTION_UP:  
                // 當觸點離開屏幕,但是屏幕上還有觸點(手指)  
            case MotionEvent.ACTION_POINTER_UP:  
                mode = 0;  
                break;  
            // 當屏幕上已經有觸點(手指),再有一個觸點壓下屏幕  
            case MotionEvent.ACTION_POINTER_DOWN:  
                mode = MODE_ZOOM;  
                /** 計算兩個手指間的距離 */  
                startDis = distance(event);  
                /** 計算兩個手指間的中間點 */  
                if (startDis > 10f) { // 兩個手指併攏在一起的時候像素大於10  
                    midPoint = mid(event);  
                    //記錄當前ImageView的縮放倍數  
                    currentMatrix.set(imageView.getImageMatrix());  
                }  
                break;  
            }  
            imageView.setImageMatrix(matrix);  
            return true;  
        }  
  
        /** 計算兩個手指間的距離 */  
        private float distance(MotionEvent event) {  
            float dx = event.getX(1) - event.getX(0);  
            float dy = event.getY(1) - event.getY(0);  
            /** 使用勾股定理返回兩點之間的距離 */  
            return FloatMath.sqrt(dx * dx + dy * dy);  
        }  
  
        /** 計算兩個手指間的中間點 */  
        private PointF mid(MotionEvent event) {  
            float midX = (event.getX(1) + event.getX(0)) / 2;  
            float midY = (event.getY(1) + event.getY(0)) / 2;  
            return new PointF(midX, midY);  
        }  
  
    }  
  
} </span>


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