Android 手势滑动,多点触摸放大缩小图片

效果展示:

OUQF8B3]Y9TE@`FPT@}7R8K

H5S1{3HT8W{$@XCTUX@CE0W

基本思路

     <1>首先写一个图片控制类ImageControl,实现对图片控制的的基本操作,我们的图片控制类ImageControl是继承自ImageView自定义的视图;

     <2>再写一个测试用的布局,这里就要用到自定义的ImageView;

     <3>编写测试类ImageViewActivity,写onTouchEvent()方法

图片控制类ImageControl:

  1 package com.basecontrol.view;
  2 
  3 import android.content.Context; 
  4 import android.graphics.Bitmap; 
  5 import android.graphics.Matrix; 
  6 import android.util.AttributeSet; 
  7 import android.util.FloatMath; 
  8 import android.view.MotionEvent; 
  9 import android.widget.ImageView;
 10 
 11 public class ImageControl extends ImageView {
 12 
 13     public ImageControl(Context context) { 
 14         super(context); 
 15     } 
 16     public ImageControl(Context context, AttributeSet attrs) { 
 17         super(context, attrs); 
 18     } 
 19     public ImageControl(Context context, AttributeSet attrs, int defStyle) { 
 20         super(context, attrs, defStyle); 
 21     } 
 22     
 23     Matrix imgMatrix=null;//定义图片的变换矩阵 
 24     
 25     static final int DOUBLE_CLICK_TIME_SPACE=300;//双击时间间隔 
 26     static final int DOUBLE_POINT_DISTANCE =10;// 两点放大两点间最小间距  
 27     static final int NONE = 0; 
 28     private int mode=NONE;//当前模式 
 29     static final int DRAG=1; 
 30     static final int ZOOM = 2; // 放大缩小操作  
 31     
 32     float bigScale=3f;//默认放大倍数 
 33     Boolean isBig=false;//是否放大 
 34     long lastClickTime =0;//单击时间 
 35     float startDistance;//两点触摸两点距离 
 36     float endDistance;//多点触摸两点距离 
 37     
 38     float topHeight;//状态栏高度和标题栏高度 
 39     Bitmap primaryBitmap=null; 
 40     
 41     float contentW;//屏幕内容区宽度 
 42     float contentH;//屏幕内容区高度 
 43     
 44     float primaryW;//原图宽度 
 45     float primaryH;//原图高度 
 46     
 47     float scale; // 适合屏幕缩放倍数  
 48     Boolean isMoveX = true; // 是否允许在X轴拖动  
 49     Boolean isMoveY = true; // 是否允许在Y轴拖动  
 50     float startX;  
 51     float startY;  
 52     float endX;  
 53     float endY;  
 54     float subX;  
 55     float subY;  
 56     float limitX1;  
 57     float limitX2;  
 58     float limitY1;  
 59     float limitY2;  
 60     ICustomMethod mCustomMethod=null; 
 61     /** 
 62      * @param bitmap 要显示的图片 
 63      * @param contentW 内容区域宽度 
 64      * @param contentH 内容区域高度 
 65      * @param topHeight 状态栏高度和标题栏高度之和 
 66      * @param iCustomMethod 
 67      */ 
 68     public void imageInit(Bitmap bitmap,int contentW,int contentH,int topHeight,ICustomMethod iCustomMethod) 
 69     { 
 70         this.primaryBitmap=bitmap; 
 71         this.contentW=contentH; 
 72         this.contentH=contentH; 
 73         this.topHeight=topHeight; 
 74         mCustomMethod=iCustomMethod; 
 75         primaryW=primaryBitmap.getWidth(); 
 76         primaryH=primaryBitmap.getHeight(); 
 77         float scaleX=(float)contentW/primaryW; 
 78         float scaleY=(float)contentH/primaryH; 
 79         scale=scaleX<scaleY?scaleX:scaleY; 
 80         if (scale<1&&1/scale<bigScale) 
 81         { 
 82             bigScale=(float)(1/scale+0.5); 
 83         } 
 84         
 85         imgMatrix=new Matrix(); 
 86         subX = (contentW-primaryW*scale)/2; 
 87         subY=(contentH-primaryH*scale)/2; 
 88         this.setImageBitmap(primaryBitmap); 
 89         this.setScaleType(ScaleType.MATRIX); 
 90         imgMatrix.postScale(scale, scale); 
 91         imgMatrix.postTranslate(subX,subY); 
 92         this.setImageMatrix(imgMatrix); 
 93     } 
 94     /** 
 95      * 按下操作 
 96      * @param event 
 97      */ 
 98     public void mouseDown(MotionEvent event) 
 99     { 
100         mode=NONE; 
101         startX=event.getRawX(); 
102         startY=event.getRawY(); 
103         if (event.getPointerCount()==1) 
104         { 
105             //如果两次时间间隔小于一定值,则默认为双击事件 
106             if (event.getEventTime()-lastClickTime<DOUBLE_CLICK_TIME_SPACE) 
107             { 
108                 changeSize(startX,startY); 
109             } 
110             else if (isBig) 
111             { 
112                 mode=DRAG; 
113             } 
114         } 
115         lastClickTime=event.getEventTime(); 
116     } 
117     /** 
118      * 非第一个点按下操作 
119      * @param event 
120      */ 
121     public void mousePointDown(MotionEvent event) 
122     { 
123         startDistance=getDistance(event); 
124         if (startDistance > DOUBLE_POINT_DISTANCE) {  
125             mode = ZOOM;  
126         } else {  
127             mode = NONE;  
128         }  
129     } 
130      public void mouseMove(MotionEvent event) 
131      {  
132         if ((mode == DRAG) && (isMoveX || isMoveY)) {  
133             float[] XY = getTranslateXY(imgMatrix);  
134             float transX = 0;  
135             float transY = 0;  
136             if (isMoveX) {  
137                 endX = event.getRawX();  
138                 transX = endX - startX;  
139                 if ((XY[0] + transX) <= limitX1) {  
140                     transX = limitX1 - XY[0];  
141                 }  
142                 if ((XY[0] + transX) >= limitX2) {  
143                     transX = limitX2 - XY[0];  
144                 }  
145             }  
146             if (isMoveY) {  
147                 endY = event.getRawY();  
148                 transY = endY - startY;  
149                 if ((XY[1] + transY) <= limitY1) {  
150                     transY = limitY1 - XY[1];  
151                 }  
152                 if ((XY[1] + transY) >= limitY2) {  
153                     transY = limitY2 - XY[1];  
154                 }  
155             }  
156   
157             imgMatrix.postTranslate(transX, transY);  
158             startX = endX;  
159             startY = endY;  
160             this.setImageMatrix(imgMatrix);  
161         } else if (mode == ZOOM && event.getPointerCount() > 1) {  
162             endDistance = getDistance(event);  
163             float dif = endDistance - startDistance;  
164             if (Math.abs(endDistance - startDistance) > DOUBLE_POINT_DISTANCE) {  
165                 if (isBig) {  
166                     if (dif < 0) {  
167                         changeSize(0, 0);  
168                         mode = NONE;  
169                     }  
170                 } else if (dif > 0) {  
171                     float x = event.getX(0) / 2 + event.getX(1) / 2;  
172                     float y = event.getY(0) / 2 + event.getY(1) / 2;  
173                     changeSize(x, y);  
174                     mode = NONE;  
175                 }  
176             }  
177         }  
178     } 
179      /** 
180       * 鼠标抬起事件 
181       */ 
182     public void mouseUp() 
183     {  
184         mode = NONE;  
185     }  
186     private void changeSize(float x, float y) {  
187         if (isBig) {  
188             // 如果处于最大状态,则还原  
189             imgMatrix.reset();  
190             imgMatrix.postScale(scale, scale);  
191             imgMatrix.postTranslate(subX, subY);  
192             isBig = false;  
193         } else {  
194             imgMatrix.postScale(bigScale, bigScale); // 在原有矩阵后乘放大倍数  
195             float transX = -((bigScale - 1) * x);  
196             float transY = -((bigScale - 1) * (y - topHeight)); // (bigScale-1)(y-statusBarHeight-subY)+2*subY;  
197             float currentWidth = primaryW * scale * bigScale; // 放大后图片大小  
198             float currentHeight = primaryH * scale * bigScale;  
199             // 如果图片放大后超出屏幕范围处理  
200             if (currentHeight > contentH) {  
201                 limitY1 = -(currentHeight - contentH); // 平移限制  
202                 limitY2 = 0;  
203                 isMoveY = true; // 允许在Y轴上拖动  
204                 float currentSubY = bigScale * subY; // 当前平移距离  
205                 // 平移后,内容区域上部有空白处理办法  
206                 if (-transY < currentSubY) {  
207                     transY = -currentSubY;  
208                 }  
209                 // 平移后,内容区域下部有空白处理办法  
210                 if (currentSubY + transY < limitY1) {  
211                     transY = -(currentHeight + currentSubY - contentH);  
212                 }  
213             } else {  
214                 // 如果图片放大后没有超出屏幕范围处理,则不允许拖动  
215                 isMoveY = false;  
216             }  
217   
218             if (currentWidth > contentW) {  
219                 limitX1 = -(currentWidth - contentW);  
220                 limitX2 = 0;  
221                 isMoveX = true;  
222                 float currentSubX = bigScale * subX;  
223                 if (-transX < currentSubX) {  
224                     transX = -currentSubX;  
225                 }  
226                 if (currentSubX + transX < limitX1) {  
227                     transX = -(currentWidth + currentSubX - contentW);  
228                 }  
229             } else {  
230                 isMoveX = false;  
231             }  
232   
233             imgMatrix.postTranslate(transX, transY);  
234             isBig = true;  
235         }  
236   
237         this.setImageMatrix(imgMatrix);  
238         if (mCustomMethod != null) {  
239             mCustomMethod.customMethod(isBig);  
240         }  
241     }  
242     /** 
243      * 获取变换矩阵中X轴偏移量和Y轴偏移量 
244      * @param matrix 
245      * @return 
246      */ 
247     private float[] getTranslateXY(Matrix matrix) 
248     {  
249         float[] values = new float[9];  
250         matrix.getValues(values);  
251         float[] floats = new float[2];  
252         floats[0] = values[Matrix.MTRANS_X];  
253         floats[1] = values[Matrix.MTRANS_Y];  
254         return floats;  
255     } 
256     /** 
257      * 获取两点间距离 
258      * @param event 
259      * @return 
260      */ 
261     private float getDistance(MotionEvent event) 
262     {  
263         float x = event.getX(0) - event.getX(1);  
264         float y = event.getY(0) - event.getY(1);  
265         return FloatMath.sqrt(x * x + y * y);  
266     }  
267     /** 
268      * 用户自定义方法 
269      * @author AILALA 
270      */ 
271     public interface ICustomMethod 
272     { 
273         public void customMethod(Boolean currentStatus); 
274     } 
275 }
ImageControl

测试布局:

 1 <?xml version="1.0" encoding="utf-8"?> 
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 3     android:layout_width="match_parent" 
 4     android:layout_height="match_parent" > 
 5     
 6     <com.basecontrol.view.ImageControl 
 7         android:id="@+id/common_imageview_imageControll" 
 8         android:layout_width="fill_parent" 
 9         android:layout_height="fill_parent" 
10         android:src="@drawable/ic_launcher"/>
11 
12     <LinearLayout 
13         android:id="@+id/common_iamgeview_llTitle" 
14         android:layout_width="wrap_content" 
15         android:layout_height="wrap_content" 
16         android:layout_alignParentLeft="true" 
17         android:layout_alignParentTop="true" > 
18   
19         <TextView 
20             android:id="@+id/common_imageview_title" 
21             android:layout_width="fill_parent" 
22             android:layout_height="wrap_content" 
23             android:text="报告"/> 
24     </LinearLayout> 
25 </RelativeLayout>
View Code

测试的Activity:

 1 package com.basecontrol.ui;
 2 
 3 import com.basecontrol.view.ImageControl; 
 4 import com.basecontrol.view.ImageControl.ICustomMethod; 
 5 import com.example.basecontrol.R; 
 6 import android.app.Activity; 
 7 import android.graphics.Bitmap; 
 8 import android.graphics.Rect; 
 9 import android.graphics.drawable.BitmapDrawable; 
10 import android.os.Bundle; 
11 import android.view.MotionEvent; 
12 import android.view.View; 
13 import android.widget.LinearLayout; 
14 import android.widget.TextView; 
15 import android.widget.Toast;
16 
17 public class ImageViewActivity extends Activity 
18 {
19 
20     @Override 
21     protected void onCreate(Bundle savedInstanceState) { 
22         super.onCreate(savedInstanceState); 
23         setContentView(R.layout.bc_common_image_view); 
24         findView(); 
25     } 
26     
27     public void onWindowFocusChanged(boolean hasFocus) 
28     { 
29         super.onWindowFocusChanged(hasFocus); 
30         init(); 
31     }; 
32     
33     ImageControl imgControl; 
34     LinearLayout llTitle; 
35     TextView tvTitle; 
36     private void findView() 
37     { 
38         imgControl=(ImageControl) findViewById(R.id.common_imageview_imageControll); 
39         llTitle=(LinearLayout) findViewById(R.id.common_iamgeview_llTitle); 
40         tvTitle=(TextView) findViewById(R.id.common_imageview_title); 
41     } 
42     
43     private void init() { 
44         tvTitle.setText("图片测试");  
45         // 这里可以为imgcontrol的图片路径动态赋值  
46         // ............  
47           
48         Bitmap bmp;  
49         if (imgControl.getDrawingCache() != null) {  
50             bmp = Bitmap.createBitmap(imgControl.getDrawingCache());  
51         } else {  
52             bmp = ((BitmapDrawable)imgControl.getDrawable()).getBitmap();  
53         }  
54         Rect frame = new Rect();  
55         getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
56         int statusBarHeight = frame.top;  
57         int screenW = this.getWindowManager().getDefaultDisplay().getWidth();  
58         int screenH = this.getWindowManager().getDefaultDisplay().getHeight()  
59                 - statusBarHeight;  
60         if (bmp != null) {  
61             imgControl.imageInit(bmp, screenW, screenH, statusBarHeight,  
62                     new ICustomMethod() {  
63                         @Override 
64                         public void customMethod(Boolean currentStatus) {  
65                             // 当图片处于放大或缩小状态时,控制标题是否显示  
66                             if (currentStatus) {  
67                                 llTitle.setVisibility(View.GONE);  
68                             } else {  
69                                 llTitle.setVisibility(View.VISIBLE);  
70                             }  
71                         } 
72                     });  
73         }  
74         else  
75         {  
76             Toast.makeText(ImageViewActivity.this, "图片加载失败,请稍候再试!", Toast.LENGTH_SHORT)  
77                     .show();  
78         }  
79   
80     } 
81     @Override 
82     public boolean onTouchEvent(MotionEvent event) { 
83         switch (event.getAction()&MotionEvent.ACTION_MASK) { 
84         case MotionEvent.ACTION_DOWN: 
85             imgControl.mouseDown(event); 
86             break; 
87         case MotionEvent.ACTION_POINTER_DOWN: 
88             imgControl.mousePointDown(event); 
89             break; 
90         case MotionEvent.ACTION_MOVE: 
91             imgControl.mouseMove(event); 
92             break; 
93         case MotionEvent.ACTION_UP: 
94             imgControl.mouseUp(); 
95             break; 
96         } 
97         return super.onTouchEvent(event); 
98     } 
99 }
ImageViewActivity

嗯,就酱…………

原文地址:https://www.cnblogs.com/wucaiyun1/p/4910934.html