蹒跚走路的程序猿

Android 移动缩放的ImageView

  今天介绍一下Android中怎么实现ImageView的缩放和移动,自定义TouchImageView。

  1 public class TouchImageView extends ImageView {
  2 
  3     Matrix matrix;
  4 
  5     // We can be in one of these 3 states
  6     static final int NONE = 0;
  7     static final int DRAG = 1;
  8     static final int ZOOM = 2;
  9     int mode = NONE;
 10 
 11     // Remember some things for zooming
 12     PointF last = new PointF();
 13     PointF start = new PointF();
 14     float minScale = 1f;
 15     float maxScale = 3f;
 16     float[] m;
 17 
 18 
 19     int viewWidth, viewHeight;
 20     static final int CLICK = 3;
 21     float saveScale = 1f;
 22     protected float origWidth, origHeight;
 23     int oldMeasuredWidth, oldMeasuredHeight;
 24 
 25 
 26     ScaleGestureDetector mScaleDetector;
 27 
 28     Context context;
 29 
 30     public TouchImageView(Context context) {
 31         super(context);
 32         sharedConstructing(context);
 33     }
 34 
 35     public TouchImageView(Context context, AttributeSet attrs) {
 36         super(context, attrs);
 37         sharedConstructing(context);
 38     }
 39     
 40     private void sharedConstructing(Context context) {
 41         super.setClickable(true);
 42         this.context = context;
 43         mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
 44         matrix = new Matrix();
 45         m = new float[9];
 46         setImageMatrix(matrix);
 47         setScaleType(ScaleType.MATRIX);
 48 
 49         setOnTouchListener(new OnTouchListener() {
 50 
 51             @Override
 52             public boolean onTouch(View v, MotionEvent event) {
 53                 mScaleDetector.onTouchEvent(event);
 54                 PointF curr = new PointF(event.getX(), event.getY());
 55 
 56                 switch (event.getAction()) {
 57                     case MotionEvent.ACTION_DOWN:
 58                         last.set(curr);
 59                         start.set(last);
 60                         mode = DRAG;
 61                         break;
 62                         
 63                     case MotionEvent.ACTION_MOVE:
 64                         if (mode == DRAG) {
 65                             float deltaX = curr.x - last.x;
 66                             float deltaY = curr.y - last.y;
 67                             float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
 68                             float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
 69                             matrix.postTranslate(fixTransX, fixTransY);
 70                             fixTrans();
 71                             last.set(curr.x, curr.y);
 72                         }
 73                         break;
 74 
 75                     case MotionEvent.ACTION_UP:
 76                         mode = NONE;
 77                         int xDiff = (int) Math.abs(curr.x - start.x);
 78                         int yDiff = (int) Math.abs(curr.y - start.y);
 79                         if (xDiff < CLICK && yDiff < CLICK)
 80                             performClick();
 81                         break;
 82 
 83                     case MotionEvent.ACTION_POINTER_UP:
 84                         mode = NONE;
 85                         break;
 86                 }
 87                 
 88                 setImageMatrix(matrix);
 89                 invalidate();
 90                 return true; // indicate event was handled
 91             }
 92 
 93         });
 94     }
 95 
 96     public void setMaxZoom(float x) {
 97         maxScale = x;
 98     }
 99 
100     private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
101         @Override
102         public boolean onScaleBegin(ScaleGestureDetector detector) {
103             mode = ZOOM;
104             return true;
105         }
106 
107         @Override
108         public boolean onScale(ScaleGestureDetector detector) {
109             float mScaleFactor = detector.getScaleFactor();
110             float origScale = saveScale;
111             saveScale *= mScaleFactor;
112             if (saveScale > maxScale) {
113                 saveScale = maxScale;
114                 mScaleFactor = maxScale / origScale;
115             } else if (saveScale < minScale) {
116                 saveScale = minScale;
117                 mScaleFactor = minScale / origScale;
118             }
119 
120             if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
121                 matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
122             else
123                 matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
124 
125             fixTrans();
126             return true;
127         }
128     }
129 
130     void fixTrans() {
131         matrix.getValues(m);
132         float transX = m[Matrix.MTRANS_X];
133         float transY = m[Matrix.MTRANS_Y];
134         
135         float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
136         float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);
137 
138         if (fixTransX != 0 || fixTransY != 0)
139             matrix.postTranslate(fixTransX, fixTransY);
140     }
141 
142     float getFixTrans(float trans, float viewSize, float contentSize) {
143         float minTrans, maxTrans;
144 
145         if (contentSize <= viewSize) {
146             minTrans = 0;
147             maxTrans = viewSize - contentSize;
148         } else {
149             minTrans = viewSize - contentSize;
150             maxTrans = 0;
151         }
152 
153         if (trans < minTrans)
154             return -trans + minTrans;
155         if (trans > maxTrans)
156             return -trans + maxTrans;
157         return 0;
158     }
159     
160     float getFixDragTrans(float delta, float viewSize, float contentSize) {
161         if (contentSize <= viewSize) {
162             return 0;
163         }
164         return delta;
165     }
166 
167     @Override
168     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
169         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
170         viewWidth = MeasureSpec.getSize(widthMeasureSpec);
171         viewHeight = MeasureSpec.getSize(heightMeasureSpec);
172         
173         //
174         // Rescales image on rotation
175         //
176         if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
177                 || viewWidth == 0 || viewHeight == 0)
178             return;
179         oldMeasuredHeight = viewHeight;
180         oldMeasuredWidth = viewWidth;
181 
182         if (saveScale == 1) {
183             //Fit to screen.
184             float scale;
185 
186             Drawable drawable = getDrawable();
187             if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
188                 return;
189             int bmWidth = drawable.getIntrinsicWidth();
190             int bmHeight = drawable.getIntrinsicHeight();
191             
192             Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
193 
194             float scaleX = (float) viewWidth / (float) bmWidth;
195             float scaleY = (float) viewHeight / (float) bmHeight;
196             scale = Math.min(scaleX, scaleY);
197             matrix.setScale(scale, scale);
198 
199             // Center the image
200             float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
201             float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
202             redundantYSpace /= (float) 2;
203             redundantXSpace /= (float) 2;
204 
205             matrix.postTranslate(redundantXSpace, redundantYSpace);
206 
207             origWidth = viewWidth - 2 * redundantXSpace;
208             origHeight = viewHeight - 2 * redundantYSpace;
209             setImageMatrix(matrix);
210         }
211         fixTrans();
212     }
213 }

 

posted on 2013-08-06 00:29  蹒跚走路的程序猿  阅读(488)  评论(0编辑  收藏  举报

导航