1. 程式人生 > >Android 過載ImageView 可以使用手勢放大縮小拖動

Android 過載ImageView 可以使用手勢放大縮小拖動

一 JAVA

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.widget.ImageView;

// by [email protected]
public class ImageTouchView extends ImageView {
	
	private PointF startPoint = new PointF();
	private Matrix matrix = new Matrix();
	private Matrix currentMaritx = new Matrix();
	
	private int mode = 0;//用於標記模式
	private static final int DRAG = 1;//拖動
	private static final int ZOOM = 2;//放大
	private float startDis = 0;
	private PointF midPoint;//中心點
	
	/** 
     * 預設建構函式 
     * @param context 
     */  
    public ImageTouchView(Context context){  
        super(context);  
    }  
    /** 
     * 該構造方法在靜態引入XML檔案中是必須的 
     * @param context 
     * @param paramAttributeSet 
     */  
    public ImageTouchView(Context context,AttributeSet paramAttributeSet){  
        super(context,paramAttributeSet);  
    }
	
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			mode = DRAG;
			currentMaritx.set(this.getImageMatrix());//記錄ImageView當期的移動位置
			startPoint.set(event.getX(),event.getY());//開始點
			break;

		case MotionEvent.ACTION_MOVE://移動事件
			if (mode == DRAG) {//圖片拖動事件
				float dx = event.getX() - startPoint.x;//x軸移動距離
				float dy = event.getY() - startPoint.y;
				matrix.set(currentMaritx);//在當前的位置基礎上移動
				matrix.postTranslate(dx, dy);
				
			} else if(mode == ZOOM){//圖片放大事件
				float endDis = distance(event);//結束距離
				if(endDis > 10f){
					float scale = endDis / startDis;//放大倍數
					//Log.v("scale=", String.valueOf(scale));
					matrix.set(currentMaritx);
					matrix.postScale(scale, scale, midPoint.x, midPoint.y);
				}
				
				
			}

			break;
			
		case MotionEvent.ACTION_UP:
			mode = 0;
			break;
		//有手指離開螢幕,但螢幕還有觸點(手指)
		case MotionEvent.ACTION_POINTER_UP:
			mode = 0;
			break;
		//當螢幕上已經有觸點(手指),再有一個手指壓下螢幕
		case MotionEvent.ACTION_POINTER_DOWN:
			mode = ZOOM;
			startDis = distance(event);
			
			if(startDis > 10f){//避免手指上有兩個繭
				midPoint = mid(event);
				currentMaritx.set(this.getImageMatrix());//記錄當前的縮放倍數
			}
			
			break;


		}
		this.setImageMatrix(matrix);
		return true;
	}
	
	/**
     * 兩點之間的距離
     * @param event
     * @return
     */
    private static 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);
    }
    /**
     * 計算兩點之間中心點的距離
     * @param event
     * @return
     */
    private static PointF mid(MotionEvent event){
    	float midx = event.getX(1) + event.getX(0);
    	float midy = event.getY(1) - event.getY(0);
    	
    	return new PointF(midx/2, midy/2);
    }

}

二 xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <com.study.drascale.ImageTouchView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/guide_0"
        android:scaleType="matrix"
        android:id="@+id/img"
        />

</LinearLayout>

By [email protected]