通過手勢實現Android ImageView 縮放
方法一:
將以下程式碼寫到MulitPointTouchListener.java中,然後對你相應的圖片進行OnTouchListener。
例如:imageView.setOnTouchListener(new MulitPointTouchListener ());
在xml中要將ImageView的縮放格式改成Matrix
例如:android:scaleType="matrix"
這樣就可以實現圖片的縮放了
下面是MulitPointTouchListener.java程式碼:
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
|
public
class
MulitPointTouchListener implements
OnTouchListener { private
static
final
String TAG = "Touch" ; //
These matrices will be used to move and zoom image Matrix
matrix = new
Matrix(); Matrix
savedMatrix = new
Matrix(); //
We can be in one of these 3 states static
final
int
NONE = 0 ; static
final
int
DRAG = 1 ; static
final
int
ZOOM = 2 ; int
mode = NONE; //
Remember some things for zooming PointF
start = new
PointF(); PointF
mid = new
PointF(); float
oldDist = 1f; @Override public
boolean
onTouch(View v, MotionEvent event) { ImageView
view = (ImageView) v; //
Log.e("view_width", //
view.getImageMatrix()..toString()+"*"+v.getWidth()); //
Dump touch event to log dumpEvent(event); //
Handle touch events here... switch
(event.getAction() & MotionEvent.ACTION_MASK) { case
MotionEvent.ACTION_DOWN: matrix.set(view.getImageMatrix()); savedMatrix.set(matrix); start.set(event.getX(),
event.getY()); //Log.d(TAG,
"mode=DRAG"); mode
= DRAG; //Log.d(TAG,
"mode=NONE"); break ; case
MotionEvent.ACTION_POINTER_DOWN: oldDist
= spacing(event); //Log.d(TAG,
"oldDist=" + oldDist); if
(oldDist > 10f) { savedMatrix.set(matrix); midPoint(mid,
event); mode
= ZOOM; //Log.d(TAG,
"mode=ZOOM"); } break ; case
MotionEvent.ACTION_UP: case
MotionEvent.ACTION_POINTER_UP: mode
= NONE; //Log.e("view.getWidth",
view.getWidth() + ""); //Log.e("view.getHeight",
view.getHeight() + ""); break ; case
MotionEvent.ACTION_MOVE: if
(mode == DRAG) { //
... matrix.set(savedMatrix); matrix.postTranslate(event.getX()
- start.x, event.getY() -
start.y); } else
if
(mode == ZOOM) { float
newDist = spacing(event); //Log.d(TAG,
"newDist=" + newDist); if
(newDist > 10f) { matrix.set(savedMatrix); float
scale = newDist / oldDist; matrix.postScale(scale,
scale, mid.x, mid.y); } } break ; } view.setImageMatrix(matrix); return
true ; //
indicate event was handled } private
void
dumpEvent(MotionEvent event) { String
names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" , "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?"
}; StringBuilder
sb = new
StringBuilder(); int
action = event.getAction(); int
actionCode = action & MotionEvent.ACTION_MASK; sb.append( "event
ACTION_" ).append(names[actionCode]); if
(actionCode == MotionEvent.ACTION_POINTER_DOWN ||
actionCode == MotionEvent.ACTION_POINTER_UP) { sb.append( "(pid
" ).append( action
>> MotionEvent.ACTION_POINTER_ID_SHIFT); sb.append( ")" ); } sb.append( "[" ); for
( int
i = 0 ;
i < event.getPointerCount(); i++) { sb.append( "#" ).append(i); sb.append( "(pid
" ).append(event.getPointerId(i)); sb.append( ")=" ).append(( int )
event.getX(i)); sb.append( "," ).append(( int )
event.getY(i)); if
(i + 1
< event.getPointerCount()) sb.append( ";" ); } sb.append( "]" ); //Log.d(TAG,
sb.toString()); } private
float
spacing(MotionEvent event) { float
x = event.getX( 0 )
- event.getX( 1 ); float
y = event.getY( 0 )
- event.getY( 1 ); return
FloatMath.sqrt(x * x + y * y); } private
void
midPoint(PointF point, MotionEvent event) { float
x = event.getX( 0 )
+ event.getX( 1 ); float
y = event.getY( 0 )
+ event.getY( 1 ); point.set(x
/ 2 ,
y / 2 ); } } |
方法二:自定義一個ImageView,例如TouchImageView:
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
import
android.content.Context; import
android.graphics.Matrix; import
android.graphics.PointF; import
android.graphics.drawable.Drawable; import
android.util.AttributeSet; import
android.util.Log; import
android.view.MotionEvent; import
android.view.ScaleGestureDetector; import
android.view.View; import
android.widget.ImageView; public
class
TouchImageView extends
ImageView { Matrix
matrix; //
We can be in one of these 3 states static
final
int
NONE = 0 ; static
final
int
DRAG = 1 ; static
final
int
ZOOM = 2 ; int
mode = NONE; //
Remember some things for zooming PointF
last = new
PointF(); PointF
start = new
PointF(); float
minScale = 1f; float
maxScale = 3f; float []
m; int
viewWidth, viewHeight; static
final
int
CLICK = 3 ; float
saveScale = 1f; protected
float
origWidth, origHeight; int
oldMeasuredWidth, oldMeasuredHeight; ScaleGestureDetector
mScaleDetector; Context
context; public
TouchImageView(Context context) { super (context); sharedConstructing(context); } public
TouchImageView(Context context, AttributeSet attrs) { super (context,
attrs); sharedConstructing(context); } private
void
sharedConstructing(Context context) { super .setClickable( true ); this .context
= context; mScaleDetector
= new
ScaleGestureDetector(context, new
ScaleListener()); matrix
= new
Matrix(); m
= new
float [ 9 ]; setImageMatrix(matrix); setScaleType(ScaleType.MATRIX); setOnTouchListener( new
OnTouchListener() { @Override public
boolean
onTouch(View v, MotionEvent event) { mScaleDetector.onTouchEvent(event); PointF
curr = new
PointF(event.getX(), event.getY()); switch
(event.getAction()) { case
MotionEvent.ACTION_DOWN: last.set(curr); start.set(last); mode
= DRAG; break ; case
MotionEvent.ACTION_MOVE: if
(mode == DRAG) { float
deltaX = curr.x - last.x; float
deltaY = curr.y - last.y; float
fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale); float
fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale); matrix.postTranslate(fixTransX,
fixTransY); fixTrans(); last.set(curr.x,
curr.y); } break ; case
MotionEvent.ACTION_UP: mode
= NONE; int
xDiff = ( int )
Math.abs(curr.x - start.x); int
yDiff = ( int )
Math.abs(curr.y - start.y); if
(xDiff < CLICK && yDiff < CLICK) performClick(); break ; case
MotionEvent.ACTION_POINTER_UP: mode
= NONE; break ; } setImageMatrix(matrix); invalidate(); return
true ; //
indicate event was handled } }); } public
void
setMaxZoom( float
x) { maxScale
= x; } private
class
ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public
boolean
onScaleBegin(ScaleGestureDetector detector) { mode
= ZOOM; return
true ; } @Override public
boolean
onScale(ScaleGestureDetector detector) { float
mScaleFactor = detector.getScaleFactor(); float
origScale = saveScale; saveScale
*= mScaleFactor; if
(saveScale > maxScale) { saveScale
= maxScale; mScaleFactor
= maxScale / origScale; } else
if
(saveScale < minScale) { saveScale
= minScale; mScaleFactor
= minScale / origScale; } if
(origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight) matrix.postScale(mScaleFactor,
mScaleFactor, viewWidth / 2 ,
viewHeight / 2 ); else matrix.postScale(mScaleFactor,
mScaleFactor, detector.getFocusX(), detector.getFocusY()); fixTrans(); return
true ; } } void
fixTrans() { matrix.getValues(m); float
transX = m[Matrix.MTRANS_X]; float
transY = m[Matrix.MTRANS_Y]; float
fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale); float
fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale); if
(fixTransX != 0
|| fixTransY != 0 ) matrix.postTranslate(fixTransX,
fixTransY); } float
getFixTrans( float
trans, float
viewSize, float
contentSize) { float
minTrans, maxTrans; if
(contentSize <= viewSize) { minTrans
= 0 ; maxTrans
= viewSize - contentSize; } else
{ minTrans
= viewSize - contentSize; maxTrans
= 0 ; } if
(trans < minTrans) return
-trans + minTrans; if
(trans > maxTrans) return
-trans + maxTrans; return
0 ; } float
getFixDragTrans( float
delta, float
viewSize, float
contentSize) { if
(contentSize <= viewSize) { return
0 ; } return
delta; } @Override protected
void
onMeasure( int
widthMeasureSpec, int
heightMeasureSpec) { super .onMeasure(widthMeasureSpec,
heightMeasureSpec); viewWidth
= MeasureSpec.getSize(widthMeasureSpec); viewHeight
= MeasureSpec.getSize(heightMeasureSpec); // //
Rescales image on rotation // if
(oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight ||
viewWidth == 0
|| viewHeight == 0 ) return ; oldMeasuredHeight
= viewHeight; oldMeasuredWidth
= viewWidth; if
(saveScale == 1 )
{ //Fit
to screen. float
scale; Drawable
drawable = getDrawable(); if
(drawable == null
|| drawable.getIntrinsicWidth() == 0
|| drawable.getIntrinsicHeight() == 0 ) return ; int
bmWidth = drawable.getIntrinsicWidth(); int
bmHeight = drawable.getIntrinsicHeight(); Log.d( "bmSize" , "bmWidth:
"
+ bmWidth + "
bmHeight : "
+ bmHeight); float
scaleX = ( float )
viewWidth / ( float )
bmWidth; float
scaleY = ( float )
viewHeight / ( float )
bmHeight; scale
= Math.min(scaleX, scaleY); matrix.setScale(scale,
scale); //
Center the image float
redundantYSpace = ( float )
viewHeight - (scale * ( float )
bmHeight); float
redundantXSpace = ( float )
viewWidth - (scale * ( float )
bmWidth); redundantYSpace
/= ( float ) 2 ; redundantXSpace
/= ( float ) 2 ; matrix.postTranslate(redundantXSpace,
redundantYSpace); origWidth
= viewWidth - 2
* redundantXSpace; origHeight
= viewHeight - 2
* redundantYSpace; setImageMatrix(matrix); } fixTrans(); } } |
然後在我們的Activity中就可以直接使用了:
1
2
3
4
5
6
7
8
9
10
11
|
public
class
TouchImageViewActivity extends
Activity { /**
Called when the activity is first created. */ @Override public
void
onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); TouchImageView
img = (TouchImageView) findViewById(R.id.snoop); img.setImageResource(R.drawable.snoopy); img.setMaxZoom(4f); } }
|
相關文章
- android imageview 縮放檢視圖片AndroidView
- 使用RxJava實現ImageView的拖動、旋轉和縮放RxJavaView
- Android 圓角、圓形 ImageView 實現AndroidView
- js實現移動端圖片預覽:手勢縮放, 手勢拖動,雙擊放大...JS
- Android通過WindowManager實現懸浮框Android
- 手機端上傳照片實現 壓縮、拖放、縮放、裁剪、合成拼圖等功能
- Android通過Chronometer控制元件實現計時功能Android控制元件
- 滑鼠懸浮圖片實現縮放效果
- QLabel顯示圖片 ,並實現縮放
- ARFoundation - 實現物體旋轉, 平移,縮放
- 通過佇列實現棧OR通過棧實現佇列佇列
- Android ImageView 清空背景圖片AndroidView
- 視覺化學習:WebGL實現縮放平移視覺化Web
- Android ImageView對齊方式設定AndroidView
- Android圖片底部居中的ImageViewAndroidView
- 通過Gradle自動實現Android元件化模組構建GradleAndroid元件化
- 直播軟體搭建,通過Android DrawerLayout實現側邊欄功能Android
- Abp 實現通過手機號註冊使用者
- LRU 實現 通過 LinkedHashMapHashMap
- 通過模板實現POI
- .NetCore實現圖片縮放與裁剪 - 基於ImageSharpNetCore
- android canvas.drawBitmap(bitmap, matrix, paint) 中 利用 matrix 實現平移到中心點及中心點縮放AndroidCanvasAI
- WPF實現手勢解鎖
- Android 幀動畫打造動態ImageViewAndroid動畫View
- Android Spingboot 實現SSE通訊案例Androidboot
- Android 手勢檢測Android
- javaScript實現鍵盤控制元素移動位置及縮放JavaScript
- Android之AppBarLayout實現懸停吸附伸縮效果AndroidAPP
- 通過redis實現session共享RedisSession
- Android Studio通過style和layer-list實現自定義進度條Android
- 通過 App Groups 實現程式間通訊APP
- Android 眼睛 顯示隱藏密碼(ImageView)Android密碼View
- android之實現跳轉手機通訊錄獲取指定姓名和手機號碼Android
- HarmonyOS NEXT應用開發之圖片縮放效果實現
- Android 手勢相關(一)Android
- Android 手勢相關(二)Android
- android 螢幕適配一:通過自定義View的方式實現適配AndroidView
- 縮放比
- 手寫IOC實現過程