在这里,我对自己的笔记本全屏截图,然后当作自定义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. //通过getDrawable获得Src的图片
  17. mDrawable=getDrawable();
  18. if(mDrawable==null)
  19. return;
  20. mDrawableWidth=mDrawable.getIntrinsicWidth();
  21. mDrawableHeight=mDrawable.getIntrinsicHeight();
  22. initImageViewSize();
  23. moveToCenter();
  24. }
  25. });
  26. }
这里唯一要注意的是我在初始化监听这个方法内,强制了ImageView的scaleType[java]view plaincopy

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

先判断一下有没有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. returntrue;
  4. }
  5. @Override
  6. publicbooleanonScaleBegin(ScaleGestureDetectordetector){
  7. returntrue;
  8. }
  9. @Override
  10. publicvoidonScaleEnd(ScaleGestureDetectordetector){
  11. }

但是,虽然实现了监听,但是然并卵,因为onTouch事件中没有它(scaleGestureDetector),在这里 ,重写onTouchEvent是没用的,因为onTouchEventListener的优先级比onTouchEvent要高,所以我们只能这样子。

  1. setOnTouchListener(this);
  1. @Override
  2. publicbooleanonTouch(Viewv,MotionEventevent){
  3. returnscaleGestureDetector.onTouchEvent(event);
  4. }
在最后调用了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. matrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY());
  16. /
  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. if(f.width()<mwidth){
  31. dX=mWidth/2-f.right+f.width()/2;
  32. }
  33. if(f.height()<mheight){
  34. dY=mHeight/2-f.bottom+f.height()/2;
  35. }
  36. matrix.postTranslate(dX,dY);
  37. 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<mheight){
  10. //往下移动
  11. dY=mHeight-f.bottom;
  12. }
  13. }

大概就是这个意思:当图片高度大于等于控件高度的时候,坚决不让控件高度方向上出现白色位置,此时,假设当图片和控件高度完全相同的时候,是不是图片的纵向刚好和控件完全重叠呢?[java]view plaincopy

  1. if(f.height()<mheight){
  2. dY=mHeight/2-f.bottom+f.height()/2;
  3. }

[java]view plaincopy

  1. privatefloatdownX;
  2. privatefloatdownY;
  3. privatefloatnowMovingX;
  4. privatefloatnowMovingY;
  5. privatefloatlastMovedX;
  6. privatefloatlastMovedY;
  7. privatebooleanisFirstMoved=false;
  8. @Override
  9. publicbooleanonTouch(Viewv,MotionEventevent){
  10. switch(event.getAction()&MotionEvent.ACTION_MASK){
  11. caseMotionEvent.ACTION_DOWN:
  12. isFirstMoved=false;
  13. downX=event.getX();
  14. downY=event.getY();
  15. break;
  16. caseMotionEvent.ACTION_POINTER_DOWN:
  17. isFirstMoved=false;
  18. break;
  19. caseMotionEvent.ACTION_MOVE:
  20. nowMovingX=event.getX();
  21. nowMovingY=event.getY();
  22. if(!isFirstMoved){
  23. isFirstMoved=true;
  24. lastMovedX=nowMovingX;
  25. lastMovedY=nowMovingY;
  26. }
  27. floatdX=0.0f;
  28. floatdY=0.0f;
  29. RectFrectf=getRectf(matrix);
  30. //判断滑动方向
  31. finalfloatscrollX=nowMovingX-lastMovedX;
  32. //判断滑动方向
  33. finalfloatscrollY=nowMovingY-lastMovedY;
  34. //图片高度大于控件高度
  35. if(rectf.height()>mHeight&&canSmoothY()){
  36. dY=nowMovingY-lastMovedY;
  37. }
  38. //图片宽度大于控件宽度
  39. if(rectf.width()>mWidth&&canSmoothX()){
  40. dX=nowMovingX-lastMovedX;
  41. }
  42. matrix.postTranslate(dX,dY);
  43. remedyXAndY(dX,dY);
  44. lastMovedX=nowMovingX;
  45. lastMovedY=nowMovingY;
  46. break;
  47. caseMotionEvent.ACTION_UP:
  48. break;
  49. caseMotionEvent.ACTION_POINTER_UP:
  50. isFirstMoved=false;
  51. break;
  52. }
  53. returnscaleGestureDetector.onTouchEvent(event);
  54. }

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

activity的xml

  1. <relativelayout
  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. <com.test.gesturedemo.view.myimageview
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:scaleType="matrix"
  10. android:src="@mipmap/tt1"/>

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

  1. Android 双击和手势的图片缩放

    2019独角兽企业重金招聘Python工程师标准>>> 代码: package com.mooc.view; import android.content.Context; impo ...

  2. android 手势事件 重写,Android实现通过手势控制图片大小缩放的方法

    本文实例讲述了Android实现通过手势控制图片大小缩放的方法.分享给大家供大家参考,具体如下: 该程序实现的是通过手势来缩放图片,从左向右挥动图片时图片被放大,从右向左挥动图片时图片被缩小,挥动速度 ...

  3. Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39480503,本文出自:[张鸿洋的博客] 上一篇已经带大家实现了自由的放大缩小图 ...

  4. android 手势放缩_手把手教你打造支持手势放大缩小的ImageView

    写在前面 最近有了新的任务,学习的时间比以前少了不少,Java回炉的文估计是得缓缓了,不过每周一篇尽量保质保量.最近感觉我文写的有点不好,因为我写东西除非必要,不然概念性的东西我基本上都是一笔带过-- ...

  5. android 布局 缩小图片大小,三大布局的基本摆放属性总结,以及imageVIew图片摆放的缩放问题...

    (一)三大布局 1.FrameLayout帧布局 Android中最简单的一种布局,默认都是放在帧布局的左上角,通过android:layout_gravity来决定子控件的位置 2.LinearLa ...

  6. android photoview 图片放大缩放功能 ImageView

    转自:http://blog.csdn.net/aaawqqq/article/details/43128111 Android 图片浏览功能  图片放大缩小 使用 photoview 双击或双指缩放 ...

  7. Android ImageView图片代码实现按屏幕宽度等比例缩放

    /*** 设置图片根据屏幕宽度进行等比例缩放* @param imageView*/public static void setImageMatchScreenWidth(ImageView imag ...

  8. Android ImageView图片显示点击背景切换

    为什么80%的码农都做不了架构师?>>>    一.介绍 ImageView用来显示任意图像图片,可以自己定义显示尺寸,显示颜色等等. 二.XML属性 android:adjustV ...

  9. android手势密码源码,Android自定义UI手势密码改进版源码下载

    在之前文章的铺垫下,再为大家分享一篇:Android手势密码,附源码下载,不要错过. 先看第一张图片的布局文件 activity_main.xml xmlns:tools="http://s ...

最新文章

  1. 《Java 8 实战》(二)—— Lambda
  2. 将特定像素点在图像上连接起来_(NeurIPS 2019) Gated CRF Loss-一种用于弱监督图像语义分割的新型损失函数...
  3. Hibernate组件(Component)映射
  4. openstack云主机无法绑定ip_智汇华云|OpenStack 虚拟机 GPU 性能优化
  5. 蓝牙BLE LINK LAYER剖析(二) -- PDU
  6. java二叉树生成器_JAVA实现二叉树生成
  7. java虚拟机和javaGC_Java虚拟机(三):GC算法和种类
  8. 2020年平均工资出炉!这个行业最高
  9. 什么是Redis的VM机制
  10. vSphere 7 With K8s系列09:部署wordpress示例
  11. UDP --01--基本开发设计
  12. 趣图:程序猿和运维狗的工作日常……
  13. python经纬度转换xy坐标公式_Python经纬度坐标转换为距离及角度的实现
  14. 多线程下载王者荣耀高清壁纸
  15. springboot优缺点
  16. 龙与地下城中的人物属性
  17. 配置树莓派中文环境 及解决 no write since last change
  18. mybatis-学习笔记-联系我获取md文档
  19. Retrofit+协程使用填坑和优化
  20. 2023春节祝福系列第一弹(下)(放飞祈福孔明灯,祝福大家身体健康)(附完整源代码及资源免费下载)

热门文章

  1. TCP UDP 学习
  2. yolov8 目标检测与跟踪
  3. .NET开源工作流ccflow流程引擎功能大全
  4. Echarts自动轮播插件echarts-auto-tooltip的使用(附停止轮播的方法)
  5. K 近邻算法(KNN)与KD 树实现
  6. 微店API,item_get - 获得微店商品详情
  7. 关于离职证明和竞业条款
  8. 长沙云图丨VR全景是什么,是怎么做出来的?
  9. 九龙证券|全市场注册制下 多层次资本市场定位更清晰
  10. 360 N6 Pro发布现场,周鸿祎为这款1699元的全面屏手机站台