Android实现 通过手势随意缩放、移动ImageView图片

在这里,我对自己的笔记本全屏截图,然后当作自定义ImageView的src内容放在真机上运行。

可以看到这里的图片是可以移动和缩放的。

在这里先说清一点,如果在xml的控件上设置src,则需要在代码上通过getDrawable();获取,如果是通过setBackGround的,则通过getBackground();获取即可。

publicclassMyImageViewextendsImageViewimplementsScaleGestureDetector.OnScaleGestureListener,

  1. 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 plain copy
  1. /**
  2. *初始化资源图片宽高
  3. */
  4. privatevoidinitImageViewSize(){
  5. if(mDrawable==null)
  6. return;
  7.  
  8. //缩放值
  9. floatscale=1.0f;
  10. //图片宽度大于控件宽度,图片高度小于控件高度
  11. if(mDrawableWidth>mWidth&&mDrawableHeight<mheight)
  12.  scale=mWidth*1.0f/mDrawableWidth;
  13. //图片高度度大于控件宽高,图片宽度小于控件宽度
  14. elseif(mDrawableHeight>mHeight&&mDrawableWidth<mwidth)
  15.  scale=mHeight*1.0f/mDrawableHeight;
  16. //图片宽度大于控件宽度,图片高度大于控件高度
  17. elseif(mDrawableHeight>mHeight&&mDrawableWidth>mWidth)
  18. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  19. //图片宽度小于控件宽度,图片高度小于控件高度
  20. elseif(mDrawableHeight<mheight&&mdrawablewidth<mwidth)
  21. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  22. mScale=scale;
  23. mMaxScale=mScale*8.0f;
  24. mMinScale=mScale*0.5f;
  25. }

先判断一下有没有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 plain copy
 
  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<mheight){
  13. //往下移动
  14. dY=mHeight-f.bottom;
  15. }
  16. }
  17. //图片宽度大于控件宽度
  18. if(f.width()>=mWidth){
  19. //图片左边出现空白
  20. if(f.left>0){
  21. //往左边移动
  22. dX=-f.left;
  23. }
  24. //图片右边出现空白
  25. if(f.right<mwidth){
  26. //往右边移动
  27. dX=mWidth-f.right;
  28. }
  29. }
  30.  
  31. if(f.width()<mwidth){
  32. dX=mWidth/2-f.right+f.width()/2;
  33. }
  34.  
  35. if(f.height()<mheight){
  36. dY=mHeight/2-f.bottom+f.height()/2;
  37. }
  38. matrix.postTranslate(dX,dY);
  39. setImageMatrix(matrix);


首先获取矩阵matrix的N维并赋值在f身上。 [java] view plain copy
  1. //图片高度大于控件高度
  2. if(f.height()>=mHeight){
  3. //图片顶部出现空白
  4. if(f.top>0){
  5. //往上移动
  6. dY=-f.top;
  7. }
  8. //图片底部出现空白
  9. if(f.bottom<mheight){
  10. //往下移动
  11. dY=mHeight-f.bottom;
  12. }
  13. }
\


大概就是这个意思:当图片高度大于等于控件高度的时候,坚决不让控件高度方向上出现白色位置,此时,假设当图片和控件高度完全相同的时候,是不是图片的纵向刚好和控件完全重叠呢? [java] view plain copy
  1. if(f.height()<mheight){
  2. dY=mHeight/2-f.bottom+f.height()/2;
  3. }
\


[java] view plain copy
  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.right<getwidth())
  8. returnfalse;
  9. returntrue;
  10. }
  11.  
  12. /**
  13. *判断y方向上可不可以滑动
  14. *@return可以滑动返回true
  15. */
  16. privatebooleancanSmoothY(){
  17. RectFrectf=getRectf(matrix);
  18. if(rectf.top>0||rectf.bottom<getheight())
  19. returnfalse;
  20. returntrue;
  21. }
以上是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&&mDrawableHeight<mheight)
  120. scale=mWidth*1.0f/mDrawableWidth;
  121. //图片高度度大于控件宽高,图片宽度小于控件宽度
  122. elseif(mDrawableHeight>mHeight&&mDrawableWidth<mwidth)
  123. scale=mHeight*1.0f/mDrawableHeight;
  124. //图片宽度大于控件宽度,图片高度大于控件高度
  125. elseif(mDrawableHeight>mHeight&&mDrawableWidth>mWidth)
  126. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  127. //图片宽度小于控件宽度,图片高度小于控件高度
  128. elseif(mDrawableHeight<mheight&&mdrawablewidth<mwidth)
  129. scale=Math.min(mHeight*1.0f/mDrawableHeight,mWidth*1.0f/mDrawableWidth);
  130. mScale=scale;
  131. mMaxScale=mScale*8.0f;
  132. mMinScale=mScale*0.5f;
  133. }
  134.  
  135. /**
  136. *移动控件中间位置
  137. */
  138. privatevoidmoveToCenter(){
  139. finalfloatdx=mWidth/2-mDrawableWidth/2;
  140. finalfloatdy=mHeight/2-mDrawableHeight/2;
  141. matrix=newMatrix();
  142. //平移至中心
  143. matrix.postTranslate(dx,dy);
  144. //以控件中心作为缩放
  145. matrix.postScale(mScale,mScale,mWidth/2,mHeight/2);
  146. setImageMatrix(matrix);
  147. }
  148.  
  149. /**
  150. *@return当前缩放的值
  151. */
  152. privatefloatgetmScale(){
  153. float[]floats=newfloat[9];
  154. matrix.getValues(floats);
  155. returnfloats[Matrix.MSCALE_X];
  156. }
  157.  
  158. /**
  159. *@parammatrix矩阵
  160. *@returnmatrix的ltbr和width,height
  161. */
  162. privateRectFgetRectf(Matrixmatrix){
  163. RectFf=newRectF();
  164. if(mDrawable==null)
  165. returnnull;
  166. f.set(0,0,mDrawableWidth,mDrawableHeight);
  167. matrix.mapRect(f);
  168. returnf;
  169. }
  170.  
  171. @Override
  172. publicbooleanonScale(ScaleGestureDetectordetector){
  173. if(mDrawable==null){
  174. returntrue;
  175. }
  176. //系统定义的缩放值
  177. floatscaleFactor=detector.getScaleFactor();
  178. //获取已经缩放的值
  179. floatscale=getmScale();
  180. floatscaleResult=scale*scaleFactor;
  181. if(scaleResult>=mMaxScale&&scaleFactor>1.0f)
  182. scaleFactor=mMaxScale/scale;
  183. if(scaleResult<=mMinScale&&scaleFactor<1.0f)
  184. scaleFactor=mMinScale/scale;
  185.  
  186. matrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY());
  187.  
  188. RectFf=getRectf(matrix);
  189. floatdX=0.0f;
  190. floatdY=0.0f;
  191. //图片高度大于控件高度
  192. if(f.height()>=mHeight){
  193. //图片顶部出现空白
  194. if(f.top>0){
  195. //往上移动
  196. dY=-f.top;
  197. }
  198. //图片底部出现空白
  199. if(f.bottom<mheight){
  200. //往下移动
  201. dY=mHeight-f.bottom;
  202. }
  203. }
  204. //图片宽度大于控件宽度
  205. if(f.width()>=mWidth){
  206. //图片左边出现空白
  207. if(f.left>0){
  208. //往左边移动
  209. dX=-f.left;
  210. }
  211. //图片右边出现空白
  212. if(f.right<mwidth){
  213. //往右边移动
  214. dX=mWidth-f.right;
  215. }
  216. }
  217.  
  218. if(f.width()<mwidth){
  219. dX=mWidth/2-f.right+f.width()/2;
  220. }
  221.  
  222. if(f.height()<mheight){
  223. dY=mHeight/2-f.bottom+f.height()/2;
  224. }
  225. matrix.postTranslate(dX,dY);
  226. setImageMatrix(matrix);
  227. returntrue;
  228. }
  229.  
  230.  
  231. @Override
  232. publicbooleanonScaleBegin(ScaleGestureDetectordetector){
  233. returntrue;
  234. }
  235.  
  236. @Override
  237. publicvoidonScaleEnd(ScaleGestureDetectordetector){
  238. floatscale=getmScale();
  239. if(scale<mscale){
  240. matrix.postScale(mScale/scale,mScale/scale,mWidth/2,mHeight/2);
  241. setImageMatrix(matrix);
  242. }
  243. }
  244.  
  245.  
  246. privatefloatdownX;
  247. privatefloatdownY;
  248. privatefloatnowMovingX;
  249. privatefloatnowMovingY;
  250. privatefloatlastMovedX;
  251. privatefloatlastMovedY;
  252. privatebooleanisFirstMoved=false;
  253.  
  254. @Override
  255. publicbooleanonTouch(Viewv,MotionEventevent){
  256. switch(event.getAction()&MotionEvent.ACTION_MASK){
  257. caseMotionEvent.ACTION_DOWN:
  258. isFirstMoved=false;
  259. downX=event.getX();
  260. downY=event.getY();
  261. break;
  262. caseMotionEvent.ACTION_POINTER_DOWN:
  263. isFirstMoved=false;
  264. break;
  265. caseMotionEvent.ACTION_MOVE:
  266. nowMovingX=event.getX();
  267. nowMovingY=event.getY();
  268. if(!isFirstMoved){
  269. isFirstMoved=true;
  270. lastMovedX=nowMovingX;
  271. lastMovedY=nowMovingY;
  272. }
  273. floatdX=0.0f;
  274. floatdY=0.0f;
  275. RectFrectf=getRectf(matrix);
  276. //判断滑动方向
  277. finalfloatscrollX=nowMovingX-lastMovedX;
  278. //判断滑动方向
  279. finalfloatscrollY=nowMovingY-lastMovedY;
  280. //图片高度大于控件高度
  281. if(rectf.height()>mHeight&&canSmoothY()){
  282. dY=nowMovingY-lastMovedY;
  283. }
  284.  
  285. //图片宽度大于控件宽度
  286. if(rectf.width()>mWidth&&canSmoothX()){
  287. dX=nowMovingX-lastMovedX;
  288. }
  289. matrix.postTranslate(dX,dY);
  290.  
  291. remedyXAndY(dX,dY);
  292.  
  293. lastMovedX=nowMovingX;
  294. lastMovedY=nowMovingY;
  295. break;
  296. caseMotionEvent.ACTION_UP:
  297. break;
  298. caseMotionEvent.ACTION_POINTER_UP:
  299. isFirstMoved=false;
  300. break;
  301. }
  302. returnscaleGestureDetector.onTouchEvent(event);
  303. }
  304.  
  305. /**
  306. *判断x方向上能不能滑动
  307. *@return可以滑动返回true
  308. */
  309. privatebooleancanSmoothX(){
  310. RectFrectf=getRectf(matrix);
  311. if(rectf.left>0||rectf.right<getwidth())
  312. returnfalse;
  313. returntrue;
  314. }
  315.  
  316. /**
  317. *判断y方向上可不可以滑动
  318. *@return可以滑动返回true
  319. */
  320. privatebooleancanSmoothY(){
  321. RectFrectf=getRectf(matrix);
  322. if(rectf.top>0||rectf.bottom<getheight())
  323. returnfalse;
  324. returntrue;
  325. }
  326.  
  327. /**
  328. *纠正出界的横和众线
  329. *@paramdx出界偏移的横线
  330. *@paramdy出街便宜的众线
  331. */
  332. privatevoidremedyXAndY(floatdx,floatdy){
  333. if(!canSmoothX())
  334. matrix.postTranslate(-dx,0);
  335. if(!canSmoothY())
  336. matrix.postTranslate(0,-dy);
  337. setImageMatrix(matrix);
  338. }
  339. }


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


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值