Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android實現 通過手勢隨意縮放、移動ImageView圖片

Android實現 通過手勢隨意縮放、移動ImageView圖片

編輯:關於Android編程

先放上一張效果圖:

\

在這裡,我對自己的筆記本全屏截圖,然後當作自定義ImageView的src內容放在真機上運行。

可以看到這裡的圖片是可以移動和縮放的。

在這裡先說清一點,如果在xml的控件上設置src,則需要在代碼上通過getDrawable();獲取,如果是通過setBackGround的,則通過getBackground();獲取即可。

  1. publicclassMyImageViewextendsImageViewimplementsScaleGestureDetector.OnScaleGestureListener,
  2. View.OnTouchListener{ 這個是我自定義ImageView的類名。

 

我在這裡實現了一些待會會用到的接口。

/**
*控件寬度
*/
privateintmWidth;
/**
*控件高度
*/
privateintmHeight;
/**
*拿到src的圖片
*/
privateDrawablemDrawable;
/**
*圖片寬度(使用前判斷mDrawable是否null)
*/
privateintmDrawableWidth;
/**
*圖片高度(使用前判斷mDrawable是否null)
*/
privateintmDrawableHeight;

/**
*初始化縮放值
*/
privatefloatmScale;

/**
*雙擊圖片的縮放值
*/
privatefloatmDoubleClickScale;

/**
*最大的縮放值
*/
privatefloatmMaxScale;

/**
*最小的縮放值
*/
privatefloatmMinScale;

privateScaleGestureDetectorscaleGestureDetector;
/**
*當前有著縮放值、平移值的矩陣。
*/
privateMatrixmatrix;

 

這些是我定義出來的一些成員變量,每個變量我都寫上了作用。
publicMyImageView(Contextcontext){
this(context,null);
}

publicMyImageView(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}

publicMyImageView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
setOnTouchListener(this);
scaleGestureDetector=newScaleGestureDetector(context,this);
initListener();
}

 

這裡是三個標准的構造器,直接用短的引用長的就是了。

 

先看一看initListener();干了什麼事情。

  1. /**
  2. *初始化事件監聽
  3. */
  4. privatevoidinitListener(){
  5. //強制設置模式
  6. setScaleType(ScaleType.MATRIX);
  7. //添加觀察者
  8. getViewTreeObserver().addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener(){
  9. @Override
  10. publicvoidonGlobalLayout(){
  11. //移除觀察者
  12. getViewTreeObserver().removeOnGlobalLayoutListener(this);
  13. //獲取控件大小
  14. mWidth=getWidth();
  15. mHeight=getHeight();
  16.  
  17. //通過getDrawable獲得Src的圖片
  18. mDrawable=getDrawable();
  19. if(mDrawable==null)
  20. return;
  21. mDrawableWidth=mDrawable.getIntrinsicWidth();
  22. mDrawableHeight=mDrawable.getIntrinsicHeight();
  23. initImageViewSize();
  24. moveToCenter();
  25. }
  26. });
  27. }
這裡唯一要注意的是我在初始化監聽這個方法內,強制了ImageView的scaleType[java]view plaincopy
  1. /**
  2. *初始化資源圖片寬高
  3. */
  4. privatevoidinitImageViewSize(){
  5. if(mDrawable==null)
  6. return;
  7.  
  8. //縮放值
  9. floatscale=1.0f;
  10. //圖片寬度大於控件寬度,圖片高度小於控件高度
  11. if(mDrawableWidth>mWidth&&mDrawableHeight scale=mWidth*1.0f/mDrawableWidth;
  12. //圖片高度度大於控件寬高,圖片寬度小於控件寬度
  13. elseif(mDrawableHeight>mHeight&&mDrawableWidth scale=mHeight*1.0f/mDrawableHeight;
  14. //圖片寬度大於控件寬度,圖片高度大於控件高度
  15. elseif(mDrawableHeight>mHeight&&mDrawableWidth>mWidth)
  16. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  17. //圖片寬度小於控件寬度,圖片高度小於控件高度
  18. elseif(mDrawableHeight scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  19. mScale=scale;
  20. mMaxScale=mScale*8.0f;
  21. mMinScale=mScale*0.5f;
  22. }

先判斷一下有沒有src資源,沒有的話,這個方法調用也沒意義了。
  1. /**
  2. *移動控件中間位置
  3. */
  4. privatevoidmoveToCenter(){
  5. finalfloatdx=mWidth/2-mDrawableWidth/2;
  6. finalfloatdy=mHeight/2-mDrawableHeight/2;
  7. matrix=newMatrix();
  8. //平移至中心
  9. matrix.postTranslate(dx,dy);
  10. //以控件中心作為縮放
  11. matrix.postScale(mScale,mScale,mWidth/2,mHeight/2);
  12. setImageMatrix(matrix);
  13. }
看注釋的意思是要把它(圖片)移動到屏幕的正中心,

dx的意思是取橫方向上,控件中心到圖片中心的值,如果大於0就向右移動,

反之向左移動相應的絕對值。

dy則換成縱向方向就是了。

在這裡實例化了matrix對象(初始化一次就行),至於為什麼只需要初始化一次,

因為圖片的縮放值和平移值,都是通過matrix保存的,如果再一次初始化,縮放值

和平移值等等數據都會被清空。

我是先讓它平時到控件正中心,然後以控件中心縮放mScale,mScale在initImageViewSize();的時候已經賦值了。

至於先縮放後平移,應該也是可以得,但可能計算公式相對麻煩些,

在這裡本著方便為主的原則,就不再作計算了。

接下來會說到這個東西scaleGestureDetector = new ScaleGestureDetector(context, this);

通過這個方法,實現了監聽事件,是手勢滑動的監聽事件。

 

[java]view plaincopy  
  1. @Override
  2. publicbooleanonScale(ScaleGestureDetectordetector){
  3.  
  4. returntrue;
  5. }
  6.  
  7.  
  8. @Override
  9. publicbooleanonScaleBegin(ScaleGestureDetectordetector){
  10. returntrue;
  11. }
  12.  
  13. @Override
  14. publicvoidonScaleEnd(ScaleGestureDetectordetector){
  15.  
  16. }
但是,雖然實現了監聽,但是然並卵,因為onTouch事件中沒有它(scaleGestureDetector),在這裡 ,重寫onTouchEvent是沒用的,因為onTouchEventListener的優先級比onTouchEvent要高,所以我們只能這樣子。
  1. setOnTouchListener(this); 
  1. @Override
  2. publicbooleanonTouch(Viewv,MotionEventevent){
  3.  
  4. returnscaleGestureDetector.onTouchEvent(event);
  5. }
在最後調用了scaleGestureDetector.onTouchEvent(event);這個方法。
然後手勢生效了(呵呵哒得意)。
  1. @Override
  2. publicbooleanonScaleBegin(ScaleGestureDetectordetector){
  3. returntrue;
  4. }
這個方法是手勢執行前生效,必須return ture,不然onScale必定失效!

現在重點說一下onScale,因為這個方法是處理手勢的縮放,

  1. @Override
  2. publicbooleanonScale(ScaleGestureDetectordetector){
  3. if(mDrawable==null){
  4. returntrue;
  5. }
  6. //系統定義的縮放值
  7. floatscaleFactor=detector.getScaleFactor();
  8. //獲取已經縮放的值
  9. floatscale=getmScale();
  10. floatscaleResult=scale*scaleFactor;
  11. if(scaleResult>=mMaxScale&&scaleFactor>1.0f)
  12. scaleFactor=mMaxScale/scale;
  13. if(scaleResult<=mMinScale&&scaleFactor<1.0f)
  14. scaleFactor=mMinScale/scale;
  15.  
  16.  
  17. matrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY());
  18.  
  19. /
 
  1. setImageMatrix(matrix);
  2. }
其中,scaleFactor是獲得手勢縮放的值(具體怎麼獲取的不知道),當值>1.0f時,說明兩個手指的滑動距離是不斷增加(相對於兩個手指都down了的那一瞬間),同理<1.0f說明兩個手指的滑動距離不斷減少,也是相對於那一瞬間,
  1. /**
  2. *@return當前縮放的值
  3. */
  4. privatefloatgetmScale(){
  5. float[]floats=newfloat[9];
  6. matrix.getValues(floats);
  7. returnfloats[Matrix.MSCALE_X];
  8. }
通過這個方法 ,拿到了之前matrix對象的scaleX值(X和Y都沒所謂,因為在這裡都是一個值),然後將當前的scale*手勢滑動的縮放值,得到最新的縮放值scaleResult,在這裡做了一個最大放大值和最小縮小值得處理,如果scaleResult大於等於最大縮放值和手指滑動為放大手勢,則讓手勢縮放為一個恆定的最大放大值(反之同理)。

 

\

看效果圖後,會覺得比較奇葩,因為縮小的時候,位置好像偏了!(原本是在控件正中心)。

  1. /**
  2. *@parammatrix矩陣
  3. *@returnmatrix的ltbr和width,height
  4. */
  5. privateRectFgetRectf(Matrixmatrix){
  6. RectFf=newRectF();
  7. if(mDrawable==null)
  8. returnnull;
  9. f.set(0,0,mDrawableWidth,mDrawableHeight);
  10. matrix.mapRect(f);
  11. returnf;
  12. }
首先看一下這個方法,通過這個方法,可以得到矩陣matrix的N維屬性,並把這N維屬性賦值到一個float類型的矩形上。

在將上面的/。。。補上

  1. RectFf=getRectf(matrix);
  2. floatdX=0.0f;
  3. floatdY=0.0f;
  4. //圖片高度大於控件高度
  5. if(f.height()>=mHeight){
  6. //圖片頂部出現空白
  7. if(f.top>0){
  8. //往上移動
  9. dY=-f.top;
  10. }
  11. //圖片底部出現空白
  12. if(f.bottom//往下移動
  13. dY=mHeight-f.bottom;
  14. }
  15. }
  16. //圖片寬度大於控件寬度
  17. if(f.width()>=mWidth){
  18. //圖片左邊出現空白
  19. if(f.left>0){
  20. //往左邊移動
  21. dX=-f.left;
  22. }
  23. //圖片右邊出現空白
  24. if(f.right//往右邊移動
  25. dX=mWidth-f.right;
  26. }
  27. }
  28.  
  29. if(f.width()dX=mWidth/2-f.right+f.width()/2;
  30. }
  31.  
  32. if(f.height()dY=mHeight/2-f.bottom+f.height()/2;
  33. }
  34. matrix.postTranslate(dX,dY);
  35. setImageMatrix(matrix);


首先獲取矩陣matrix的N維並賦值在f身上。[java]view plaincopy
  1. //圖片高度大於控件高度
  2. if(f.height()>=mHeight){
  3. //圖片頂部出現空白
  4. if(f.top>0){
  5. //往上移動
  6. dY=-f.top;
  7. }
  8. //圖片底部出現空白
  9. if(f.bottom//往下移動
  10. dY=mHeight-f.bottom;
  11. }
  12. }
\
大概就是這個意思:當圖片高度大於等於控件高度的時候,堅決不讓控件高度方向上出現白色位置,此時,假設當圖片和控件高度完全相同的時候,是不是圖片的縱向剛好和控件完全重疊呢?[java]view plaincopy
  1. if(f.height()dY=mHeight/2-f.bottom+f.height()/2;
  2. }
\
[java]view plaincopy
  1. privatefloatdownX;
  2. privatefloatdownY;
  3. privatefloatnowMovingX;
  4. privatefloatnowMovingY;
  5. privatefloatlastMovedX;
  6. privatefloatlastMovedY;
  7. privatebooleanisFirstMoved=false;
  8.  
  9. @Override
  10. publicbooleanonTouch(Viewv,MotionEventevent){
  11. switch(event.getAction()&MotionEvent.ACTION_MASK){
  12. caseMotionEvent.ACTION_DOWN:
  13. isFirstMoved=false;
  14. downX=event.getX();
  15. downY=event.getY();
  16. break;
  17. caseMotionEvent.ACTION_POINTER_DOWN:
  18. isFirstMoved=false;
  19. break;
  20. caseMotionEvent.ACTION_MOVE:
  21. nowMovingX=event.getX();
  22. nowMovingY=event.getY();
  23. if(!isFirstMoved){
  24. isFirstMoved=true;
  25. lastMovedX=nowMovingX;
  26. lastMovedY=nowMovingY;
  27. }
  28. floatdX=0.0f;
  29. floatdY=0.0f;
  30. RectFrectf=getRectf(matrix);
  31. //判斷滑動方向
  32. finalfloatscrollX=nowMovingX-lastMovedX;
  33. //判斷滑動方向
  34. finalfloatscrollY=nowMovingY-lastMovedY;
  35. //圖片高度大於控件高度
  36. if(rectf.height()>mHeight&&canSmoothY()){
  37. dY=nowMovingY-lastMovedY;
  38. }
  39.  
  40. //圖片寬度大於控件寬度
  41. if(rectf.width()>mWidth&&canSmoothX()){
  42. dX=nowMovingX-lastMovedX;
  43. }
  44. matrix.postTranslate(dX,dY);
  45.  
  46. remedyXAndY(dX,dY);
  47.  
  48. lastMovedX=nowMovingX;
  49. lastMovedY=nowMovingY;
  50. break;
  51. caseMotionEvent.ACTION_UP:
  52. break;
  53. caseMotionEvent.ACTION_POINTER_UP:
  54. isFirstMoved=false;
  55. break;
  56. }
  57. returnscaleGestureDetector.onTouchEvent(event);
  58. }

MotionEvent.ACTION_POINTER_DOWN;這個也是壓下的時候,區別在於只有不是第一根手指壓下的時候才執行,

 

所以,我在壓下的動作都初始化isFirstMoved=false;

當移動的時候,ACTION_MOVE也會執行。

由於移動的時候處理邏輯少的問題,出現屏幕越界後明顯的白邊反彈,因此在這裡編輯了一部分代碼。。。

滑動前,先判斷能否滑動,滑動後,再次判斷是否越界,因此,有效解決了白邊反彈現象。

  1. /**
  2. *判斷x方向上能不能滑動
  3. *@return可以滑動返回true
  4. */
  5. privatebooleancanSmoothX(){
  6. RectFrectf=getRectf(matrix);
  7. if(rectf.left>0||rectf.rightreturnfalse;
  8. returntrue;
  9. }
  10.  
  11. /**
  12. *判斷y方向上可不可以滑動
  13. *@return可以滑動返回true
  14. */
  15. privatebooleancanSmoothY(){
  16. RectFrectf=getRectf(matrix);
  17. if(rectf.top>0||rectf.bottomreturnfalse;
  18. returntrue;
  19. }
以上是x和y方向上,滑動前判斷可不可以滑動的片段代碼。
  1. /**
  2. *糾正出界的橫和眾線
  3. *@paramdx出界偏移的橫線
  4. *@paramdy出街便宜的眾線
  5. */
  6. privatevoidremedyXAndY(floatdx,floatdy){
  7. if(!canSmoothX())
  8. matrix.postTranslate(-dx,0);
  9. if(!canSmoothY())
  10. matrix.postTranslate(0,-dy);
  11. setImageMatrix(matrix);
  12. }
這段是用於滑動之後判斷是否越界的,如果越界,把多余的dx和dy滑動回去。

完整的自定義控件代碼:

  1. packagecom.test.gesturedemo.view;
  2.  
  3. importandroid.content.Context;
  4. importandroid.graphics.Matrix;
  5. importandroid.graphics.RectF;
  6. importandroid.graphics.drawable.Drawable;
  7. importandroid.util.AttributeSet;
  8. importandroid.view.MotionEvent;
  9. importandroid.view.ScaleGestureDetector;
  10. importandroid.view.View;
  11. importandroid.view.ViewTreeObserver;
  12. importandroid.widget.ImageView;
  13.  
  14. /**
  15. *Createdby13798on2016/6/3.
  16. */
  17. publicclassMyImageViewextendsImageViewimplementsScaleGestureDetector.OnScaleGestureListener,View.OnTouchListener{
  18. /**
  19. *控件寬度
  20. */
  21. privateintmWidth;
  22. /**
  23. *控件高度
  24. */
  25. privateintmHeight;
  26. /**
  27. *拿到src的圖片
  28. */
  29. privateDrawablemDrawable;
  30. /**
  31. *圖片寬度(使用前判斷mDrawable是否null)
  32. */
  33. privateintmDrawableWidth;
  34. /**
  35. *圖片高度(使用前判斷mDrawable是否null)
  36. */
  37. privateintmDrawableHeight;
  38.  
  39. /**
  40. *初始化縮放值
  41. */
  42. privatefloatmScale;
  43.  
  44. /**
  45. *雙擊圖片的縮放值
  46. */
  47. privatefloatmDoubleClickScale;
  48.  
  49. /**
  50. *最大的縮放值
  51. */
  52. privatefloatmMaxScale;
  53.  
  54. /**
  55. *最小的縮放值
  56. */
  57. privatefloatmMinScale;
  58.  
  59. privateScaleGestureDetectorscaleGestureDetector;
  60. /**
  61. *當前有著縮放值、平移值的矩陣。
  62. */
  63. privateMatrixmatrix;
  64.  
  65. publicMyImageView(Contextcontext){
  66. this(context,null);
  67. }
  68.  
  69. publicMyImageView(Contextcontext,AttributeSetattrs){
  70. this(context,attrs,0);
  71. }
  72.  
  73. publicMyImageView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
  74. super(context,attrs,defStyleAttr);
  75. setOnTouchListener(this);
  76. scaleGestureDetector=newScaleGestureDetector(context,this);
  77. initListener();
  78. }
  79.  
  80.  
  81. /**
  82. *初始化事件監聽
  83. */
  84. privatevoidinitListener(){
  85. //強制設置模式
  86. setScaleType(ScaleType.MATRIX);
  87. //添加觀察者
  88. getViewTreeObserver().addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener(){
  89. @Override
  90. publicvoidonGlobalLayout(){
  91. //移除觀察者
  92. getViewTreeObserver().removeGlobalOnLayoutListener(this);
  93. //獲取控件大小
  94. mWidth=getWidth();
  95. mHeight=getHeight();
  96.  
  97. //通過getDrawable獲得Src的圖片
  98. mDrawable=getDrawable();
  99. if(mDrawable==null)
  100. return;
  101. mDrawableWidth=mDrawable.getIntrinsicWidth();
  102. mDrawableHeight=mDrawable.getIntrinsicHeight();
  103. initImageViewSize();
  104. moveToCenter();
  105. }
  106. });
  107. }
  108.  
  109. /**
  110. *初始化資源圖片寬高
  111. */
  112. privatevoidinitImageViewSize(){
  113. if(mDrawable==null)
  114. return;
  115.  
  116. //縮放值
  117. floatscale=1.0f;
  118. //圖片寬度大於控件寬度,圖片高度小於控件高度
  119. if(mDrawableWidth>mWidth&&mDrawableHeightscale=mWidth*1.0f/mDrawableWidth;
  120. //圖片高度度大於控件寬高,圖片寬度小於控件寬度
  121. elseif(mDrawableHeight>mHeight&&mDrawableWidthscale=mHeight*1.0f/mDrawableHeight;
  122. //圖片寬度大於控件寬度,圖片高度大於控件高度
  123. elseif(mDrawableHeight>mHeight&&mDrawableWidth>mWidth)
  124. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  125. //圖片寬度小於控件寬度,圖片高度小於控件高度
  126. elseif(mDrawableHeightscale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  127. mScale=scale;
  128. mMaxScale=mScale*8.0f;
  129. mMinScale=mScale*0.5f;
  130. }
  131.  
  132. /**
  133. *移動控件中間位置
  134. */
  135. privatevoidmoveToCenter(){
  136. finalfloatdx=mWidth/2-mDrawableWidth/2;
  137. finalfloatdy=mHeight/2-mDrawableHeight/2;
  138. matrix=newMatrix();
  139. //平移至中心
  140. matrix.postTranslate(dx,dy);
  141. //以控件中心作為縮放
  142. matrix.postScale(mScale,mScale,mWidth/2,mHeight/2);
  143. setImageMatrix(matrix);
  144. }
  145.  
  146. /**
  147. *@return當前縮放的值
  148. */
  149. privatefloatgetmScale(){
  150. float[]floats=newfloat[9];
  151. matrix.getValues(floats);
  152. returnfloats[Matrix.MSCALE_X];
  153. }
  154.  
  155. /**
  156. *@parammatrix矩陣
  157. *@returnmatrix的ltbr和width,height
  158. */
  159. privateRectFgetRectf(Matrixmatrix){
  160. RectFf=newRectF();
  161. if(mDrawable==null)
  162. returnnull;
  163. f.set(0,0,mDrawableWidth,mDrawableHeight);
  164. matrix.mapRect(f);
  165. returnf;
  166. }
  167.  
  168. @Override
  169. publicbooleanonScale(ScaleGestureDetectordetector){
  170. if(mDrawable==null){
  171. returntrue;
  172. }
  173. //系統定義的縮放值
  174. floatscaleFactor=detector.getScaleFactor();
  175. //獲取已經縮放的值
  176. floatscale=getmScale();
  177. floatscaleResult=scale*scaleFactor;
  178. if(scaleResult>=mMaxScale&&scaleFactor>1.0f)
  179. scaleFactor=mMaxScale/scale;
  180. if(scaleResult<=mMinScale&&scaleFactor<1.0f)
  181. scaleFactor=mMinScale/scale;
  182.  
  183. matrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY());
  184.  
  185. RectFf=getRectf(matrix);
  186. floatdX=0.0f;
  187. floatdY=0.0f;
  188. //圖片高度大於控件高度
  189. if(f.height()>=mHeight){
  190. //圖片頂部出現空白
  191. if(f.top>0){
  192. //往上移動
  193. dY=-f.top;
  194. }
  195. //圖片底部出現空白
  196. if(f.bottom//往下移動
  197. dY=mHeight-f.bottom;
  198. }
  199. }
  200. //圖片寬度大於控件寬度
  201. if(f.width()>=mWidth){
  202. //圖片左邊出現空白
  203. if(f.left>0){
  204. //往左邊移動
  205. dX=-f.left;
  206. }
  207. //圖片右邊出現空白
  208. if(f.right//往右邊移動
  209. dX=mWidth-f.right;
  210. }
  211. }
  212.  
  213. if(f.width()dX=mWidth/2-f.right+f.width()/2;
  214. }
  215.  
  216. if(f.height()dY=mHeight/2-f.bottom+f.height()/2;
  217. }
  218. matrix.postTranslate(dX,dY);
  219. setImageMatrix(matrix);
  220. returntrue;
  221. }
  222.  
  223.  
  224. @Override
  225. publicbooleanonScaleBegin(ScaleGestureDetectordetector){
  226. returntrue;
  227. }
  228.  
  229. @Override
  230. publicvoidonScaleEnd(ScaleGestureDetectordetector){
  231. floatscale=getmScale();
  232. if(scalematrix.postScale(mScale/scale,mScale/scale,mWidth/2,mHeight/2);
  233. setImageMatrix(matrix);
  234. }
  235. }
  236.  
  237.  
  238. privatefloatdownX;
  239. privatefloatdownY;
  240. privatefloatnowMovingX;
  241. privatefloatnowMovingY;
  242. privatefloatlastMovedX;
  243. privatefloatlastMovedY;
  244. privatebooleanisFirstMoved=false;
  245.  
  246. @Override
  247. publicbooleanonTouch(Viewv,MotionEventevent){
  248. switch(event.getAction()&MotionEvent.ACTION_MASK){
  249. caseMotionEvent.ACTION_DOWN:
  250. isFirstMoved=false;
  251. downX=event.getX();
  252. downY=event.getY();
  253. break;
  254. caseMotionEvent.ACTION_POINTER_DOWN:
  255. isFirstMoved=false;
  256. break;
  257. caseMotionEvent.ACTION_MOVE:
  258. nowMovingX=event.getX();
  259. nowMovingY=event.getY();
  260. if(!isFirstMoved){
  261. isFirstMoved=true;
  262. lastMovedX=nowMovingX;
  263. lastMovedY=nowMovingY;
  264. }
  265. floatdX=0.0f;
  266. floatdY=0.0f;
  267. RectFrectf=getRectf(matrix);
  268. //判斷滑動方向
  269. finalfloatscrollX=nowMovingX-lastMovedX;
  270. //判斷滑動方向
  271. finalfloatscrollY=nowMovingY-lastMovedY;
  272. //圖片高度大於控件高度
  273. if(rectf.height()>mHeight&&canSmoothY()){
  274. dY=nowMovingY-lastMovedY;
  275. }
  276.  
  277. //圖片寬度大於控件寬度
  278. if(rectf.width()>mWidth&&canSmoothX()){
  279. dX=nowMovingX-lastMovedX;
  280. }
  281. matrix.postTranslate(dX,dY);
  282.  
  283. remedyXAndY(dX,dY);
  284.  
  285. lastMovedX=nowMovingX;
  286. lastMovedY=nowMovingY;
  287. break;
  288. caseMotionEvent.ACTION_UP:
  289. break;
  290. caseMotionEvent.ACTION_POINTER_UP:
  291. isFirstMoved=false;
  292. break;
  293. }
  294. returnscaleGestureDetector.onTouchEvent(event);
  295. }
  296.  
  297. /**
  298. *判斷x方向上能不能滑動
  299. *@return可以滑動返回true
  300. */
  301. privatebooleancanSmoothX(){
  302. RectFrectf=getRectf(matrix);
  303. if(rectf.left>0||rectf.rightreturnfalse;
  304. returntrue;
  305. }
  306.  
  307. /**
  308. *判斷y方向上可不可以滑動
  309. *@return可以滑動返回true
  310. */
  311. privatebooleancanSmoothY(){
  312. RectFrectf=getRectf(matrix);
  313. if(rectf.top>0||rectf.bottomreturnfalse;
  314. returntrue;
  315. }
  316.  
  317. /**
  318. *糾正出界的橫和眾線
  319. *@paramdx出界偏移的橫線
  320. *@paramdy出街便宜的眾線
  321. */
  322. privatevoidremedyXAndY(floatdx,floatdy){
  323. if(!canSmoothX())
  324. matrix.postTranslate(-dx,0);
  325. if(!canSmoothY())
  326. matrix.postTranslate(0,-dy);
  327. setImageMatrix(matrix);
  328. }
  329. }


activity的xml
  1.  
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6.  
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:scaleType="matrix"
  10. android:src="@mipmap/tt1"/>
  11.  

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved