我是靠谱客的博主 贤惠冷风,这篇文章主要介绍Android ImageView移动和缩放,现在分享给大家,希望可以做个参考。

要实现ImageView的缩放就要使用到我们大学里面学习的线代里面的矩阵(Matrix),我们看一下源码就可以知道

复制代码
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
public static final int MSCALE_X = 0; //!< use with getValues/setValues public static final int MSKEW_X = 1; //!< use with getValues/setValues public static final int MTRANS_X = 2; //!< use with getValues/setValues public static final int MSKEW_Y = 3; //!< use with getValues/setValues public static final int MSCALE_Y = 4; //!< use with getValues/setValues public static final int MTRANS_Y = 5; //!< use with getValues/setValues public static final int MPERSP_0 = 6; //!< use with getValues/setValues public static final int MPERSP_1 = 7; //!< use with getValues/setValues public static final int MPERSP_2 = 8; //!< use with getValues/setValues @Override public String toString() { StringBuilder sb = new StringBuilder(64); sb.append("Matrix{"); toShortString(sb); sb.append('}'); return sb.toString(); } public void toShortString(StringBuilder sb) { float[] values = new float[9]; getValues(values); sb.append('['); sb.append(values[0]); sb.append(", "); sb.append(values[1]); sb.append(", "); sb.append(values[2]); sb.append("]["); sb.append(values[3]); sb.append(", "); sb.append(values[4]); sb.append(", "); sb.append(values[5]); sb.append("]["); sb.append(values[6]); sb.append(", "); sb.append(values[7]); sb.append(", "); sb.append(values[8]); sb.append(']'); }

这其实就是一个3*3的矩阵,然后我们就可以知道具体的坐标属性为
{MSCALE_X,MSKEW_X,MTRANS_X,
MSKEW_Y, MSCALE_Y,MTRANS_Y,
MPERSP_0,MPERSP_1,MPERSP_2}
其中 MSCALE_X和MSCALE_Y分别是控制X轴和Y轴方向的缩放,MSKEW_X和MSKEW_Y分别是控制X坐标和Y坐标的线性倾斜系数,MTRANS_X和MTRANS_Y分别是控制X方向和Y方向的线性平移。MPERSP_0、MPERSP_1和MPERSP_2是关于透视的,我们这里使用不到也就不做解释了。
这个矩阵其实也是一个默认的单位矩阵,单位矩阵为

复制代码
1
2
3
4
E=(1,0,0 0,1,0 0,0,1)

也就是在默认的情况下我们的矩阵对ImageView的缩放、平移是保持着默认的状态的。当我们的手指在屏幕上面移动的时候,所谓的单位矩阵里面的坐标值就会发生变化。
先看一下效果图:
这里写图片描述
我们这次要实现的是关于图片的移动与缩放。但是图片的缩放是要有限制的,图片既不能无限的缩小更不能无限的放大,那么我们就需要对图片的放大和缩小进行限制了。怎么限制呢?我刚刚已经说了,当我们的手指在屏幕上面移动时,矩阵坐标值就会发生变化。那么我们就可以根据MSCALE_X和MSCALE_Y来对X和Y的坐标值进行一个限制。
怎么获取获取的大小呢?我们可以通过获取缩放后的图片大小来获取MSCALE_X和和MSCALE_Y的值。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
img_test.post(new Runnable(){ @Override public void run() { //获得图片的真实宽高, int drawableWidth = img_test.getDrawable().getBounds().width(); int drawableHeight = img_test.getDrawable().getBounds().height(); //获得变换矩阵以后的图片 Matrix matrix = img_test.getImageMatrix(); float[] values = new float[9]; matrix.getValues(values); //获取变化矩阵中的MSCALE_X和MSCALE_Y的值 float scaleX = values[0]; float scaleY = values[4]; } });

获取到MSCALE_X和MSCALE_Y变化的值以后我们就可以根据变化的值做相应的判断。
如果我们的图片特别大以至于宽或高已经超出了屏幕的宽或高,我们又想要显示出来的效果的宽或高正好是屏幕的宽或高。我们可以获取图片的真实的宽和高,然后屏幕的宽和高,最后用图片的真是宽或高/屏幕的宽或高进行缩放
获取屏幕的分辨率
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
要想获取图片的真是高度,我们就要先获取资源图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
剩下的就是获取缩放的比例了
float defaultScale = Math.min(
((float) displayMetrics.widthPixels / (float) bitmap.getWidth()),
((float) displayMetrics.heightPixels / (float) bitmap.getHeight()));
下面我们开始进行图片的缩放,就需要处理触摸事件了。代码里面已经做了详细的注释就不再解释了。

复制代码
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package com.lyxrobert.imagezoom; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; public class ImageViewZoomAty extends Activity implements View.OnTouchListener { Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); DisplayMetrics displayMetrics; ImageView img_test; Bitmap bitmap; float defaultScale ;// 最小缩放比例 static final int NONE = 0;// 初始状态 static final int DRAG = 1;// 拖动状态 static final int ZOOM = 2;// 缩放状态 int mode = NONE; PointF pointF = new PointF(); PointF mid = new PointF(); float scaleX = 0; float scaleY = 0; float dist = 1f; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img_test = (ImageView) findViewById(R.id.img_test);// 获取控件 bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);// 获取图片资源 img_test.setImageBitmap(bitmap);// 填充控件 img_test.setOnTouchListener(this);// 设置触屏监听 displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);// 获取分辨率 defaulZoom(); center(true,true); img_test.setImageMatrix(matrix); } /** * 触屏监听 */ public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { // 单指按下 case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); pointF.set(event.getX(), event.getY()); mode = DRAG; break; //另外的手指按下 case MotionEvent.ACTION_POINTER_DOWN: dist = space2Point(event); // 如果连续获取的两点之间的距离大于10f说明是多点触摸模式 if (space2Point(event) > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix.set(savedMatrix); matrix.postTranslate(event.getX() - pointF.x, event.getY() - pointF.y); } else if (mode == ZOOM) { float moveDistance = space2Point(event); if (moveDistance > 10f) { img_test.post(new Runnable(){ @Override public void run() { //获得图片的变换矩阵 Matrix m = img_test.getImageMatrix(); float[] values = new float[9]; m.getValues(values); //获取变化矩阵中的MSCALE_X和MSCALE_Y的值 scaleX = values[0]; scaleY = values[4]; if (scaleX<0.8f){ mode = NONE; float minScale =0.81f/scaleX; matrix.postScale(minScale, minScale, mid.x, mid.y); }else if(scaleX>2.5f){ mode = NONE; float maxScale =2.5f/scaleX; matrix.postScale(maxScale, maxScale, mid.x, mid.y); } }}); matrix.set(savedMatrix); float tScale = moveDistance / dist; matrix.postScale(tScale, tScale, mid.x, mid.y); } } break; } img_test.setImageMatrix(matrix); center(true,true); return true; } /** * 为了适应屏幕的宽或高,需要做适度的缩放 */ private void defaulZoom() { defaultScale = Math.min( ((float) displayMetrics.widthPixels / (float) bitmap.getWidth()), ((float) displayMetrics.heightPixels / (float) bitmap.getHeight())); matrix.postScale(defaultScale, defaultScale); } /** * 让图片居中显示 */ protected void center(boolean isHorizontal, boolean isVertical) { Matrix m = new Matrix(); m.set(matrix); //设置的图片显示的位置在左上角 RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (isVertical) { int screenHeight = displayMetrics.heightPixels; if (height < screenHeight) { //如果图片的高度小于屏幕的高度,那么就要向下移动图片,因为上面的rect设置的图片默认显示在左上角 deltaY = (screenHeight - height) / 2 - rect.top; } else if (rect.top > 0) { //说明图片的高度大于屏幕的高度并且上面留有空白需要上移 deltaY = -rect.top; } else if (rect.bottom < screenHeight) { //说明图片的高度大于屏幕的高度并且下面留有空白需要下移 deltaY = img_test.getHeight() - rect.bottom; } } if (isHorizontal) { int screenWidth = displayMetrics.widthPixels; if (width < screenWidth) { //如果图片的宽度小于屏幕的宽度,那么就要右移动图片,因为上面的rect设置的图片默认显示在左上角 deltaX = (screenWidth - width) / 2 - rect.left; } else if (rect.left > 0) { //说明图片的宽度大于屏幕的宽度并且左边留有空白需要右移 deltaX = -rect.left; } else if (rect.right < screenWidth) { //说明图片的宽度大于屏幕的宽度并且右边留有空白需要左移 deltaX = screenWidth - rect.right; } } matrix.postTranslate(deltaX, deltaY); } /** * 两点的距离 */ float distanceX; float distanceY; private float space2Point(MotionEvent event) { try { distanceX = event.getX(0) - event.getX(1); distanceY = event.getY(0) - event.getY(1); return (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY); }catch (Exception e){ } return (float) Math.sqrt(distanceX * distanceX+ distanceY * distanceY); } /** * 两点的中点 */ private void midPoint(PointF point, MotionEvent event) { float midX = event.getX(0) + event.getX(1); float midY = event.getY(0) + event.getY(1); point.set(midX / 2, midY / 2); } }

布局文件activity_main

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent" > <ImageView android:layout_width="match_parent" android:id="@+id/img_test" android:scaleType="matrix" android:src="@drawable/test" android:layout_height="match_parent"> </ImageView> </LinearLayout>

点击下载源码

这里写图片描述

最后

以上就是贤惠冷风最近收集整理的关于Android ImageView移动和缩放的全部内容,更多相关Android内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部