效果展示:

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

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

基本思路

     <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

相关文章: