定義ImageView,實現功能以下:java
1.初始化時圖片垂直居中顯示,拉伸圖片寬度至ImageView寬度。android
2.使用兩根手指放大縮小圖片,可設置最大放大倍數,當圖片小於ImageView寬度時,在手指離開屏幕時恢復到ImageView寬度。git
3.支持雙擊放大縮小。當圖片處於未放大狀態時,雙擊放大至指定倍數,當圖片處於放大狀態時,雙擊恢復至未放大狀態。github
4.圖片拖動效果。當圖片處於未放大狀態時,不可拖動。數組
5.圖片拖動效果。當放大後的高度不超過ImageView時,不可垂直拖動。(因爲默認設置拉伸寬度至ImageView寬度,水平方向可不判斷)。ide
6.圖片拖動效果。當圖片向右拖動時,若左邊緣超出左邊界,則中止水平拖動。同理上下右邊緣,即拖動後不會看到背景留白。函數
首先講一下原理,圖片放大縮小無非就是使用Matrix類,而這裏經過手勢控制,那天然是須要監聽onTouch事件,因此原理簡單來講,就是經過監聽onTouch的各類事件來控制Matrix類了。其中具體控制方式以下:post
onTouch | Matrix | 輔助操做 |
ACTION_DOWN | 無 | 記錄初始點,設置本次模式爲拖動模式,ScaleType設置成Matrix |
ACTION_POINTER_DOWN | 無 | 設置本次模式爲縮放模式 |
ACTION_MOVE | 根據模式執行postScale或postTranslate | |
ACTION_UP | 根據當前縮放級別決定是否重置Matrix | |
雙擊 | postScale | |
ACTION_CANCEL | 同UP |
如今開始,按功能點一一列代碼說明:this
首先自定義ImageView,因爲和Matrix有關,取名爲MatrixImageView.java,繼承於ImageView.javaspa
public class MatrixImageView extends ImageView{ private final static String TAG="MatrixImageView"; private GestureDetector mGestureDetector; /** 模板Matrix,用以初始化 */ private Matrix mMatrix=new Matrix(); /** 圖片長度*/ private float mImageWidth; /** 圖片高度 */ private float mImageHeight; public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); MatrixTouchListener mListener=new MatrixTouchListener(); setOnTouchListener(mListener); mGestureDetector=new GestureDetector(getContext(), new GestureListener(mListener)); //背景設置爲balck setBackgroundColor(Color.BLACK); //將縮放類型設置爲FIT_CENTER,表示把圖片按比例擴大/縮小到View的寬度,居中顯示 setScaleType(ScaleType.FIT_CENTER); }
因爲用到了雙擊縮放效果,在此引用了手勢類 GestureDetector,GestureListener就是繼承與SimpleOnGestureListener的手勢監聽類了。MatrixTouchListener繼承與onTouchListner,是Touch事件監聽的主體。在構造函數最後一句setScaleType(ScaleType.FIT_CENTER),即是知足功能一的要點。
接下去,重寫setImageBitmap方法。
@Override public void setImageBitmap(Bitmap bm) { // TODO Auto-generated method stub super.setImageBitmap(bm); //設置完圖片後,獲取該圖片的座標變換矩陣 mMatrix.set(getImageMatrix()); float[] values=new float[9]; mMatrix.getValues(values); //圖片寬度爲屏幕寬度除縮放倍數 mImageWidth=getWidth()/values[Matrix.MSCALE_X]; mImageHeight=(getHeight()-values[Matrix.MTRANS_Y]*2)/values[Matrix.MSCALE_Y]; }
在此是爲了初始化幾個重要的變量:
mMatrix:圖片的原始Matrix,記錄下來做爲模板,以後的變化都是在這個Matrix的基礎上進行 |
mImageWidth:圖片的真實寬度,注意這個寬度是指圖片在ImageView中的真實寬度,非顯示寬度也非文件寬度。當咱們把圖片放入ImageView中時,會根據ImageView的寬高進行一個轉換,轉換結果記錄在Matrix中。咱們根據顯示寬度與Matrix進行計算得到真實寬度。 |
mImageHeight:同寬度。 |
三種寬度的區別(非官方叫法,只爲理解)
顯示寬度:ImageView中的圖片(Bitmap、Drawable)在ImageView中顯示的高度,是經過Matrix計算以後的寬度。當放大圖片時,這個寬度可能超過ImageView的寬度。 |
真實寬度:ImageView中的圖片在Matrix計算以前的寬度。當ImageView寬爲390,圖片X軸縮放級別爲0.5,一個填充滿ImageView的X軸的圖片的真實寬度爲780。這個寬度和ImageView的ScaleType相關。 |
文件寬度:文件X軸分辨率,不必定等於真實寬度。 |
之因此在sitImageView中進行設置,是由於每次ImageView更換圖片後這些變量都會跟着改變,咱們只須要和當前圖片相關的這些變量。若但願在layout中設置圖片而不是代碼中設置,請把上述代碼移至構造函數。
接下來是重點的onTouch事件:
public class MatrixTouchListener implements OnTouchListener{ /** 拖拉照片模式 */ private static final int MODE_DRAG = 1; /** 放大縮小照片模式 */ private static final int MODE_ZOOM = 2; /** 不支持Matrix */ private static final int MODE_UNABLE=3; /** 最大縮放級別*/ float mMaxScale=6; /** 雙擊時的縮放級別*/ float mDobleClickScale=2; private int mMode = 0;// /** 縮放開始時的手指間距 */ private float mStartDis; /** 當前Matrix*/ private Matrix mCurrentMatrix = new Matrix(); /** 用於記錄開始時候的座標位置 */ private PointF startPoint = new PointF(); @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: //設置拖動模式 mMode=MODE_DRAG; startPoint.set(event.getX(), event.getY()); // isMatrixEnable(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: reSetMatrix(); break; case MotionEvent.ACTION_MOVE: if (mMode == MODE_ZOOM) { setZoomMatrix(event); }else if (mMode==MODE_DRAG) { setDragMatrix(event); } break; case MotionEvent.ACTION_POINTER_DOWN: if(mMode==MODE_UNABLE) return true; mMode=MODE_ZOOM; mStartDis = distance(event); break; default: break; } return mGestureDetector.onTouchEvent(event); }
/** * 計算兩個手指間的距離 * @param event * @return */ private float distance(MotionEvent event) { float dx = event.getX(1) - event.getX(0); float dy = event.getY(1) - event.getY(0); /** 使用勾股定理返回兩點之間的距離 */ return (float) Math.sqrt(dx * dx + dy * dy); }
首先能夠看到,在ACTION_DOWN和ACTION_POINTER_DOWN中主要是進行當前事件模式的肯定。當咱們按下一個點時,會觸發Down事件,而按下第二個點後,又會觸發Action_Pointer_Down事件,在此咱們把按下一個點標記爲拖動事件,按下兩個點標記爲縮放事件。先跟蹤縮放事件方法setZoomMatrix(event);
/** * 設置縮放Matrix * @param event */ private void setZoomMatrix(MotionEvent event) { //只有同時觸屏兩個點的時候才執行 if(event.getPointerCount()<2) return; float endDis = distance(event);// 結束距離 if (endDis > 10f) { // 兩個手指併攏在一塊兒的時候像素大於10 float scale = endDis / mStartDis;// 獲得縮放倍數 mStartDis=endDis;//重置距離 mCurrentMatrix.set(getImageMatrix());//初始化Matrix float[] values=new float[9]; mCurrentMatrix.getValues(values); scale = checkMaxScale(scale, values); setImageMatrix(mCurrentMatrix); } }
首先咱們判斷是否點擊了兩個點,若是不是直接返回。接着,使用distance方法計算出兩個點之間的距離。以前在Action_Pointer_Down中已經計算出了初始距離,這裏計算出的是移動後的兩個點的距離。經過這兩個距離咱們能夠得出本次移動的縮放倍數,但這還沒完,咱們須要驗證這個縮放倍數是否越界了:
/** * 檢驗scale,使圖像縮放後不會超出最大倍數 * @param scale * @param values * @return */ private float checkMaxScale(float scale, float[] values) { if(scale*values[Matrix.MSCALE_X]>mMaxScale) scale=mMaxScale/values[Matrix.MSCALE_X]; mCurrentMatrix.postScale(scale, scale,getWidth()/2,getHeight()/2); return scale; }
咱們獲取了Matrix矩陣中保存的數組,在這個數組中,values[Matrix.MSCALE_X](事實上就是數組的第0個)表明了X軸的縮放級別,判斷一下圖片當前的縮放級別再乘以剛獲得的scale後是否回去越界,會的話就將其控制在邊界值。以後,以ImageView的中心點爲原點,在當前Matrix的基礎上進行指定倍數的縮放。
在Move事件中縮放時咱們只會阻止超越最大值的縮放,在UP事件中咱們會對小於原始縮放值的縮放進行重置。方法reSetMatrix以下。
/** * 重置Matrix */ private void reSetMatrix() { if(checkRest()){ mCurrentMatrix.set(mMatrix); setImageMatrix(mCurrentMatrix); } } /** * 判斷是否須要重置 * @return 當前縮放級別小於模板縮放級別時,重置 */ private boolean checkRest() { // TODO Auto-generated method stub float[] values=new float[9]; getImageMatrix().getValues(values); //獲取當前X軸縮放級別 float scale=values[Matrix.MSCALE_X]; //獲取模板的X軸縮放級別,二者作比較 mMatrix.getValues(values); return scale<values[Matrix.MSCALE_X]; }
首先獲取當前X軸縮放級別(因爲默認拉伸寬度至ImageView寬度,縮放級別以X軸爲準),再經過模板Matrix獲得原始的X軸縮放級別,判斷當前縮放級別是否小於模板縮放級別,若小於,則重置成模板縮放級別。
接下去是雙擊放大縮小圖片效果,該功能在手勢接口GestureListener中完成,主要代碼以下:
private class GestureListener extends SimpleOnGestureListener{ private final MatrixTouchListener listener; public GestureListener(MatrixTouchListener listener) { this.listener=listener; } @Override public boolean onDown(MotionEvent e) { //捕獲Down事件 return true; } @Override public boolean onDoubleTap(MotionEvent e) { //觸發雙擊事件 listener.onDoubleClick(); return true; }
/** * 雙擊時觸發 */ public void onDoubleClick(){ float scale=isZoomChanged()?1:mDobleClickScale; mCurrentMatrix.set(mMatrix);//初始化Matrix mCurrentMatrix.postScale(scale, scale,getWidth()/2,getHeight()/2); setImageMatrix(mCurrentMatrix); } /** * 判斷縮放級別是不是改變過 * @return true表示非初始值,false表示初始值 */ private boolean isZoomChanged() { float[] values=new float[9]; getImageMatrix().getValues(values); //獲取當前X軸縮放級別 float scale=values[Matrix.MSCALE_X]; //獲取模板的X軸縮放級別,二者作比較 mMatrix.getValues(values); return scale!=values[Matrix.MSCALE_X]; }
在構造函數中將onTouchListner傳遞來進來。在此只重寫兩個方法:Down和onDoubleTap,只有在Down事件中返回true,onDoubleTap才能正常觸發。
在onDoubleClick事件中,首先經過isZoomChanged方法判斷當前的縮放級別是不是模板Matrix的縮放級別,是的話將縮放倍數設置爲2倍,否的話設置成1倍。在載入模板Matrix,在此基礎上作縮放。
最後是圖片拖動效果setDragMatrix()
public void setDragMatrix(MotionEvent event) { if(isZoomChanged()){ float dx = event.getX() - startPoint.x; // 獲得x軸的移動距離 float dy = event.getY() - startPoint.y; // 獲得x軸的移動距離 //避免和雙擊衝突,大於10f纔算是拖動 if(Math.sqrt(dx*dx+dy*dy)>10f){ startPoint.set(event.getX(), event.getY()); //在當前基礎上移動 mCurrentMatrix.set(getImageMatrix()); float[] values=new float[9]; mCurrentMatrix.getValues(values); dx=checkDxBound(values,dx); dy=checkDyBound(values,dy); mCurrentMatrix.postTranslate(dx, dy); setImageMatrix(mCurrentMatrix); } } }
首先是經過isZoomChanged方法判斷是否縮放過,若未縮放過則不可拖動(這種狀況下圖片全貌均可以看到,不須要拖動)。接着,拿當前座標和按下時記錄的startPoint座標進行計算,得出拖動的距離。須要注意的是,在此須要對拖動距離作一個判斷,當其小於10f時不進行拖動,不然會和雙擊事件衝突(在雙擊事件前一樣會觸發Move事件,二者一同執行的話,雙擊的縮放沒法正常工做)。當肯定開始拖動的以後,先重置startPoint的座標,接着,開始驗證當前移動的位移量是否合法。
/** *和當前矩陣對比,檢驗dx,使圖像移動後不會超出ImageView邊界 * @param values * @param dx * @return */ private float checkDxBound(float[] values,float dx) { float width=getWidth(); if(mImageWidth*values[Matrix.MSCALE_X]<width) return 0; if(values[Matrix.MTRANS_X]+dx>0) dx=-values[Matrix.MTRANS_X]; else if(values[Matrix.MTRANS_X]+dx<-(mImageWidth*values[Matrix.MSCALE_X]-width)) dx=-(mImageWidth*values[Matrix.MSCALE_X]-width)-values[Matrix.MTRANS_X]; return dx; } /** * 和當前矩陣對比,檢驗dy,使圖像移動後不會超出ImageView邊界 * @param values * @param dy * @return */ private float checkDyBound(float[] values, float dy) { float height=getHeight(); if(mImageHeight*values[Matrix.MSCALE_Y]<height) return 0; if(values[Matrix.MTRANS_Y]+dy>0) dy=-values[Matrix.MTRANS_Y]; else if(values[Matrix.MTRANS_Y]+dy<-(mImageHeight*values[Matrix.MSCALE_Y]-height)) dy=-(mImageHeight*values[Matrix.MSCALE_Y]-height)-values[Matrix.MTRANS_Y]; return dy; }
以Y軸爲例,首先獲取ImageView高度,再經過sitImageBitmap方法中獲取的圖片真實高度和當前Y軸縮放級別計算出當前Y軸的顯示高度。若是顯示高度小於ImageView高度,表示當前顯示的圖片尚未ImageView高,在Y軸不須要移動均可看清全貌,Y軸位移量直接返回0。
假如顯示高度超過了ImageView高度,獲取圖片當前在Y軸的位移量(values[Matrix.MTRANS_Y]值),將其加上計算出的位移量後是否大於0,若大於0,表示圖片上邊緣將會離開ImageView上邊緣,須要從新計算位移量。若上述條件不成立,判斷當前位移量加上計算後的位移量,是否小於圖片顯示高度-屏幕高度,若小於表示圖片下邊緣將離開ImageView下邊緣,一樣須要從新計算。最後返回計算的Y軸偏移量。X軸同理。最後使用驗證過的X、Y軸偏移量,在當前圖片Matrix的基礎上行進行偏移。
最後貼下完整代碼,Demo的話,能夠到個人照相機Demo裏查看,該功能爲相冊功能的一部分。
package com.linj.album.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.PointF; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; /** * @ClassName: MatrixImageView * @Description: 帶放大、縮小、移動效果的ImageView * @author LinJ * @date 2015-1-7 上午11:15:07 * */ public class MatrixImageView extends ImageView{ private final static String TAG="MatrixImageView"; private GestureDetector mGestureDetector; /** 模板Matrix,用以初始化 */ private Matrix mMatrix=new Matrix(); /** 圖片長度*/ private float mImageWidth; /** 圖片高度 */ private float mImageHeight; public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); MatrixTouchListener mListener=new MatrixTouchListener(); setOnTouchListener(mListener); mGestureDetector=new GestureDetector(getContext(), new GestureListener(mListener)); //背景設置爲balck setBackgroundColor(Color.BLACK); //將縮放類型設置爲FIT_CENTER,表示把圖片按比例擴大/縮小到View的寬度,居中顯示 setScaleType(ScaleType.FIT_CENTER); } @Override public void setImageBitmap(Bitmap bm) { // TODO Auto-generated method stub super.setImageBitmap(bm); //設置完圖片後,獲取該圖片的座標變換矩陣 mMatrix.set(getImageMatrix()); float[] values=new float[9]; mMatrix.getValues(values); //圖片寬度爲屏幕寬度除縮放倍數 mImageWidth=getWidth()/values[Matrix.MSCALE_X]; mImageHeight=(getHeight()-values[Matrix.MTRANS_Y]*2)/values[Matrix.MSCALE_Y]; } public class MatrixTouchListener implements OnTouchListener{ /** 拖拉照片模式 */ private static final int MODE_DRAG = 1; /** 放大縮小照片模式 */ private static final int MODE_ZOOM = 2; /** 不支持Matrix */ private static final int MODE_UNABLE=3; /** 最大縮放級別*/ float mMaxScale=6; /** 雙擊時的縮放級別*/ float mDobleClickScale=2; private int mMode = 0;// /** 縮放開始時的手指間距 */ private float mStartDis; /** 當前Matrix*/ private Matrix mCurrentMatrix = new Matrix(); /** 用於記錄開始時候的座標位置 */ private PointF startPoint = new PointF(); @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: //設置拖動模式 mMode=MODE_DRAG; startPoint.set(event.getX(), event.getY()); isMatrixEnable(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: reSetMatrix(); break; case MotionEvent.ACTION_MOVE: if (mMode == MODE_ZOOM) { setZoomMatrix(event); }else if (mMode==MODE_DRAG) { setDragMatrix(event); } break; case MotionEvent.ACTION_POINTER_DOWN: if(mMode==MODE_UNABLE) return true; mMode=MODE_ZOOM; mStartDis = distance(event); break; default: break; } return mGestureDetector.onTouchEvent(event); } public void setDragMatrix(MotionEvent event) { if(isZoomChanged()){ float dx = event.getX() - startPoint.x; // 獲得x軸的移動距離 float dy = event.getY() - startPoint.y; // 獲得x軸的移動距離 //避免和雙擊衝突,大於10f纔算是拖動 if(Math.sqrt(dx*dx+dy*dy)>10f){ startPoint.set(event.getX(), event.getY()); //在當前基礎上移動 mCurrentMatrix.set(getImageMatrix()); float[] values=new float[9]; mCurrentMatrix.getValues(values); dx=checkDxBound(values,dx); dy=checkDyBound(values,dy); mCurrentMatrix.postTranslate(dx, dy); setImageMatrix(mCurrentMatrix); } } } /** * 判斷縮放級別是不是改變過 * @return true表示非初始值,false表示初始值 */ private boolean isZoomChanged() { float[] values=new float[9]; getImageMatrix().getValues(values); //獲取當前X軸縮放級別 float scale=values[Matrix.MSCALE_X]; //獲取模板的X軸縮放級別,二者作比較 mMatrix.getValues(values); return scale!=values[Matrix.MSCALE_X]; } /** * 和當前矩陣對比,檢驗dy,使圖像移動後不會超出ImageView邊界 * @param values * @param dy * @return */ private float checkDyBound(float[] values, float dy) { float height=getHeight(); if(mImageHeight*values[Matrix.MSCALE_Y]<height) return 0; if(values[Matrix.MTRANS_Y]+dy>0) dy=-values[Matrix.MTRANS_Y]; else if(values[Matrix.MTRANS_Y]+dy<-(mImageHeight*values[Matrix.MSCALE_Y]-height)) dy=-(mImageHeight*values[Matrix.MSCALE_Y]-height)-values[Matrix.MTRANS_Y]; return dy; } /** *和當前矩陣對比,檢驗dx,使圖像移動後不會超出ImageView邊界 * @param values * @param dx * @return */ private float checkDxBound(float[] values,float dx) { float width=getWidth(); if(mImageWidth*values[Matrix.MSCALE_X]<width) return 0; if(values[Matrix.MTRANS_X]+dx>0) dx=-values[Matrix.MTRANS_X]; else if(values[Matrix.MTRANS_X]+dx<-(mImageWidth*values[Matrix.MSCALE_X]-width)) dx=-(mImageWidth*values[Matrix.MSCALE_X]-width)-values[Matrix.MTRANS_X]; return dx; } /** * 設置縮放Matrix * @param event */ private void setZoomMatrix(MotionEvent event) { //只有同時觸屏兩個點的時候才執行 if(event.getPointerCount()<2) return; float endDis = distance(event);// 結束距離 if (endDis > 10f) { // 兩個手指併攏在一塊兒的時候像素大於10 float scale = endDis / mStartDis;// 獲得縮放倍數 mStartDis=endDis;//重置距離 mCurrentMatrix.set(getImageMatrix());//初始化Matrix float[] values=new float[9]; mCurrentMatrix.getValues(values); scale = checkMaxScale(scale, values); setImageMatrix(mCurrentMatrix); } } /** * 檢驗scale,使圖像縮放後不會超出最大倍數 * @param scale * @param values * @return */ private float checkMaxScale(float scale, float[] values) { if(scale*values[Matrix.MSCALE_X]>mMaxScale) scale=mMaxScale/values[Matrix.MSCALE_X]; mCurrentMatrix.postScale(scale, scale,getWidth()/2,getHeight()/2); return scale; } /** * 重置Matrix */ private void reSetMatrix() { if(checkRest()){ mCurrentMatrix.set(mMatrix); setImageMatrix(mCurrentMatrix); } } /** * 判斷是否須要重置 * @return 當前縮放級別小於模板縮放級別時,重置 */ private boolean checkRest() { // TODO Auto-generated method stub float[] values=new float[9]; getImageMatrix().getValues(values); //獲取當前X軸縮放級別 float scale=values[Matrix.MSCALE_X]; //獲取模板的X軸縮放級別,二者作比較 mMatrix.getValues(values); return scale<values[Matrix.MSCALE_X]; } /** * 判斷是否支持Matrix */ private void isMatrixEnable() { //當加載出錯時,不可縮放 if(getScaleType()!=ScaleType.CENTER){ setScaleType(ScaleType.MATRIX); }else { mMode=MODE_UNABLE;//設置爲不支持手勢 } } /** * 計算兩個手指間的距離 * @param event * @return */ private float distance(MotionEvent event) { float dx = event.getX(1) - event.getX(0); float dy = event.getY(1) - event.getY(0); /** 使用勾股定理返回兩點之間的距離 */ return (float) Math.sqrt(dx * dx + dy * dy); } /** * 雙擊時觸發 */ public void onDoubleClick(){ float scale=isZoomChanged()?1:mDobleClickScale; mCurrentMatrix.set(mMatrix);//初始化Matrix mCurrentMatrix.postScale(scale, scale,getWidth()/2,getHeight()/2); setImageMatrix(mCurrentMatrix); } } private class GestureListener extends SimpleOnGestureListener{ private final MatrixTouchListener listener; public GestureListener(MatrixTouchListener listener) { this.listener=listener; } @Override public boolean onDown(MotionEvent e) { //捕獲Down事件 return true; } @Override public boolean onDoubleTap(MotionEvent e) { //觸發雙擊事件 listener.onDoubleClick(); return true; } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return super.onFling(e1, e2, velocityX, velocityY); } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub super.onShowPress(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { // TODO Auto-generated method stub return super.onDoubleTapEvent(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { // TODO Auto-generated method stub return super.onSingleTapConfirmed(e); } } }
注:當該ImageView在其餘ViewGroup中,如經常使用的ViewPager中時,Move事件會和ViewGroup事件衝突。在劃屏進行ViewPager的Item切換時,Viewpager將會經過onInterceptTouchEvent方法攔截掉,返回給ImageView一個Cancel事件,這種狀況下須要重寫ViewGroup的onInterceptTouchEvent方法。