我是靠谱客的博主 健壮冰淇淋,这篇文章主要介绍Android可平移缩放旋转的ImageView的实现,现在分享给大家,希望可以做个参考。

本文是在别人做的ImageView实现缩放,平移功能的基础上做了优化并加上了旋转功能.
一,缩放
缩放通过双击屏幕和双指移动实现.
1,双击缩放
通过GestureDetector获取双击事件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onDoubleTap(MotionEvent e) { //如果此刻正在进行自动的缓慢缩放,则禁止用户双击缩放 if (isAutoScale){ return true; } float x = e.getX(); float y = e.getY(); if (getScale() < mMidScale) { postDelayed(new AutoScaleRunnable(mMidScale,x,y),16); } else { postDelayed(new AutoScaleRunnable(mInitScale,getWidth()/2,getHeight()/2),16); } isAutoScale = true; return true; }
复制代码
1
2
3
双击后我们可以直接把图片缩放到指定的大小,但是为了提高用户体验,我们通过postDelayed(Runnable action, long delayMillis) 实现过程缩放,我们看AutoScaleRunnable
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//实现缓慢缩放 private class AutoScaleRunnable implements Runnable{ //缩放的目标比例 private float mTargetScale; //缩放的中心点 private float x; private float y; private final float BIGGER = 1.07f; private final float SMALLER = 0.93f; //临时缩放比例 private float tempScale; public AutoScaleRunnable(float mTargetScale,float x,float y) { this.mTargetScale = mTargetScale; this.x = x; this.y = y; if (getScale() < mTargetScale) { tempScale = BIGGER; } if (getScale() > mTargetScale) { tempScale = SMALLER; } } @Override public void run() { //进行缩放 mMatrix.postScale(tempScale,tempScale,x,y); checkBorderAndCenterWhenScale(); setImageMatrix(mMatrix); float currentScale = getScale(); //如果可以放大或者缩小 if ((tempScale > 1.0f && currentScale < mTargetScale) || (tempScale < 1.0f && currentScale > mTargetScale) ){ postDelayed(this,16); } //设置为目标缩放比例 else { float scale = mTargetScale / currentScale; mMatrix.postScale(scale,scale,x,y); checkBorderAndCenterWhenScale(); setImageMatrix(mMatrix); isAutoScale = false; } } }

1,先根据getScale()和mTargetScale判断是缩小还是放大并得到tempScale.其中BIGGER和SMALLER是指每次缩放倍数.
2,然后每次缩放tempScale倍,判断currentScale和mTargetScale,如果还可以放大或缩小,则继续postDelayed(this,16);
3,直到放大中currentScale > mTargetScale或缩小中currentScale < mTargetScale。则设置为目标缩放比例进行最后一次缩放.
每次缩放都要进行边界以及位置的控制,参看checkBorderAndCenterWhenScale()

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//在缩放的时候进行边界以及位置的控制 private void checkBorderAndCenterWhenScale() { RectF rectf = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); //缩放时进行边界检测,防止出现留白 if (rectf.width() >= width) { if (rectf.left > 0) { deltaX = -rectf.left; } if (rectf.right < width) { deltaX = width - rectf.right; } } if (rectf.height() >= height) { if (rectf.top > 0) { deltaY = -rectf.top; } if (rectf.bottom < height) { deltaY = height - rectf.bottom; } } //如果宽度或者高度小于控件的宽度或高度,则让其居中 if (rectf.width() < width) { deltaX = width / 2f - rectf.right + rectf.width() / 2f; } if (rectf.height() < height) { deltaY = height / 2f - rectf.bottom + rectf.height() / 2f; } mMatrix.postTranslate(deltaX,deltaY); }

2,手指多点触控缩放
通过ScaleGestureDetector实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.OnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { //获取当前图片的缩放比例 float scale = getScale(); //多点触控缩放比例 float scaleFactor = detector.getScaleFactor(); if (getDrawable() == null){ return true; } //进行缩放范围的控制 if ((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)) { if (scale * scaleFactor < mInitScale) { scaleFactor = mInitScale / scale; } if (scale * scaleFactor > mMaxScale) { scaleFactor = mMaxScale / scale; } //缩放 mMatrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY()); //在缩放的时候进行边界以及位置的控制 checkBorderAndCenterWhenScale(); setImageMatrix(mMatrix); } return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } });

onScale中获取当前图片的缩放比例scale和多点触控缩放比例scaleFactor,进行缩放范围的控制后做缩放处理.
3,平移
平移要在onTouchEvent中,由于手势的优先级高,所以把mGestureDetector.onTouchEvent(event)和mScaleGestureDetector.onTouchEvent(event);
放在前面,注释比较清楚,不做详解

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@Override public boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } mScaleGestureDetector.onTouchEvent(event); float x = 0; float y = 0; int pointerCount = event.getPointerCount(); //累加x和y方向的距离 for (int i = 0; i < pointerCount; i++){ x += event.getX(i); y += event.getY(i); } //获得中心点位置 x /= pointerCount; y /= pointerCount; if (mLastPointerCount != pointerCount) { isCanDrag = false; mLastX = x; mLastY = y; } mLastPointerCount = pointerCount; RectF rectF = getMatrixRectF(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: /** * 此View在ViewPager中使用时,图片放大后自由移动的事件会与 * ViewPager的左右切换的事件发生冲突,导致图片放大后如果左右 * 移动时不能自由移动图片,而是使ViewPager切换图片.这是由于事 * 件分发时外层的优先级比内层的高,使用下列判断可以解决 */ if (rectF.width() > getWidth() || rectF.height() > getHeight()) { getParent().requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_MOVE: if (rectF.width() > getWidth() || rectF.height() > getHeight()) { getParent().requestDisallowInterceptTouchEvent(true); } //偏移量 float dx = x - mLastX; float dy = y - mLastY; if (!isCanDrag){ isCanDrag = isMoveAction(dx,dy); } if (isCanDrag) { if (getDrawable() != null) { isCheckLeftAndRight = true; isCheckTopAndBottom = true; //如果宽度小于控件的宽度,不允许横向移动 if (rectF.width() < getWidth()) { isCheckLeftAndRight = false; dx = 0; } //如果高度小于控件的高度,不允许纵向移动 if (rectF.height() < getHeight()) { isCheckTopAndBottom = false; dy = 0; } mMatrix.postTranslate(dx,dy); //当自由移动时进行边界检查,防止留白 checkBorderWhenTranslate(); setImageMatrix(mMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mLastPointerCount = 0; break; } return true; }

4,旋转
对mMatrix做postRotate操作即可.

复制代码
1
2
3
4
5
6
public void rotate(int i) { mMatrix.postRotate(i,getWidth()/2,getHeight()/2); checkBorderAndCenterWhenScale(); setImageMatrix(mMatrix); }

5,getScale()方法
这个方法在多个地方调用,就是获取当前的scale
这里需要注意的是获取scale时,我们是从矩阵中获取MSCALE_X或MSCALE_Y
这里写图片描述
但旋转了以后就不能获取MSCALE_X了,如下矩阵:
0.72 0.0 -3.0517578E-5
0.0 0.72 -36.48004
0.0 0.0 1.0
旋转90°后变成这样
0.0 -0.72 1500.48
0.72 0.0 383.99997
0.0 0.0 1.0
此时我们就需要获取MSKEW_X或MSKEW_Y并取其绝对值

复制代码
1
2
3
4
5
6
7
//获取当前图片的缩放比例 public float getScale(){ float[] values = new float[9]; mMatrix.getValues(values); return values[Matrix.MSCALE_X]==0?Math.abs(values[Matrix.MSKEW_X]):Math.abs(values[Matrix.MSCALE_X]); }

代码地址:http://download.csdn.net/download/bigboysunshine/10025059

最后

以上就是健壮冰淇淋最近收集整理的关于Android可平移缩放旋转的ImageView的实现的全部内容,更多相关Android可平移缩放旋转内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部