41.Android之图片放大缩小学习

生活中经常会用到图片放大和缩小,今天简单学习下.

思路:1.添加一个操作图片放大和缩小类;  2. 布局文件中引用这个自定义控件;  3. 主Activity一些修改. 代码如下:

增加图片操作类

  1 package com.example.imagezoomdemo;
  2 
  3 import java.util.Observable;
  4 import java.util.Observer;
  5 
  6 import android.content.Context;
  7 import android.graphics.Bitmap;
  8 import android.graphics.Canvas;
  9 import android.graphics.Paint;
 10 import android.graphics.Rect;
 11 import android.util.AttributeSet;
 12 import android.util.Log;
 13 import android.view.MotionEvent;
 14 import android.view.View;
 15 
 16 public class zoomimage extends View implements Observer {
 17 
 18     /** Paint object used when drawing bitmap. */
 19     private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
 20 
 21     /** Rectangle used (and re-used) for cropping source image. */
 22     private final Rect mRectSrc = new Rect();
 23 
 24     /** Rectangle used (and re-used) for specifying drawing area on canvas. */
 25     private final Rect mRectDst = new Rect();
 26 
 27     /** Object holding aspect quotient */
 28     private final AspectQuotient mAspectQuotient = new AspectQuotient();
 29 
 30     /** The bitmap that we're zooming in, and drawing on the screen. */
 31     private Bitmap mBitmap;
 32 
 33     /** State of the zoom. */
 34     private ZoomState mState;
 35 
 36     private BasicZoomControl mZoomControl;
 37     private BasicZoomListener mZoomListener;
 38 
 39     public zoomimage(Context context, AttributeSet attrs) {
 40         super(context, attrs);
 41 
 42         mZoomControl = new BasicZoomControl();
 43 
 44         mZoomListener = new BasicZoomListener();
 45         mZoomListener.setZoomControl(mZoomControl);
 46 
 47         setZoomState(mZoomControl.getZoomState());
 48 
 49         setOnTouchListener(mZoomListener);
 50 
 51         mZoomControl.setAspectQuotient(getAspectQuotient());
 52     }
 53 
 54     public void zoomImage(float f, float x, float y) {
 55         mZoomControl.zoom(f, x, y);
 56     }
 57 
 58     public void setImage(Bitmap bitmap) {
 59         mBitmap = bitmap;
 60 
 61         mAspectQuotient.updateAspectQuotient(getWidth(), getHeight(),
 62                 mBitmap.getWidth(), mBitmap.getHeight());
 63         mAspectQuotient.notifyObservers();
 64 
 65         invalidate();
 66     }
 67 
 68     private void setZoomState(ZoomState state) {
 69         if (mState != null) {
 70             mState.deleteObserver(this);
 71         }
 72 
 73         mState = state;
 74         mState.addObserver(this);
 75 
 76         invalidate();
 77     }
 78 
 79     private AspectQuotient getAspectQuotient() {
 80         return mAspectQuotient;
 81     }
 82 
 83     @Override
 84     protected void onDraw(Canvas canvas) {
 85         if (mBitmap != null && mState != null) {
 86 
 87             Log.d("ZoomImageView", "OnDraw");
 88 
 89             final float aspectQuotient = mAspectQuotient.get();
 90 
 91             final int viewWidth = getWidth();
 92             final int viewHeight = getHeight();
 93             final int bitmapWidth = mBitmap.getWidth();
 94             final int bitmapHeight = mBitmap.getHeight();
 95 
 96             Log.d("ZoomImageView", "viewWidth = " + viewWidth);
 97             Log.d("ZoomImageView", "viewHeight = " + viewHeight);
 98             Log.d("ZoomImageView", "bitmapWidth = " + bitmapWidth);
 99             Log.d("ZoomImageView", "bitmapHeight = " + bitmapHeight);
100 
101             final float panX = mState.getPanX();
102             final float panY = mState.getPanY();
103             final float zoomX = mState.getZoomX(aspectQuotient) * viewWidth
104                     / bitmapWidth;
105             final float zoomY = mState.getZoomY(aspectQuotient) * viewHeight
106                     / bitmapHeight;
107 
108             // Setup source and destination rectangles
109             mRectSrc.left = (int) (panX * bitmapWidth - viewWidth / (zoomX * 2));
110             mRectSrc.top = (int) (panY * bitmapHeight - viewHeight
111                     / (zoomY * 2));
112             mRectSrc.right = (int) (mRectSrc.left + viewWidth / zoomX);
113             mRectSrc.bottom = (int) (mRectSrc.top + viewHeight / zoomY);
114             // mRectDst.left = getLeft();
115             mRectDst.left = 0;
116             mRectDst.top = 0;
117             // mRectDst.right = getRight();
118             mRectDst.right = getWidth();
119             mRectDst.bottom = getHeight();
120 
121             // Adjust source rectangle so that it fits within the source image.
122             if (mRectSrc.left < 0) {
123                 mRectDst.left += -mRectSrc.left * zoomX;
124                 mRectSrc.left = 0;
125             }
126             if (mRectSrc.right > bitmapWidth) {
127                 mRectDst.right -= (mRectSrc.right - bitmapWidth) * zoomX;
128                 mRectSrc.right = bitmapWidth;
129             }
130             if (mRectSrc.top < 0) {
131                 mRectDst.top += -mRectSrc.top * zoomY;
132                 mRectSrc.top = 0;
133             }
134             if (mRectSrc.bottom > bitmapHeight) {
135                 mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY;
136                 mRectSrc.bottom = bitmapHeight;
137             }
138 
139             mRectDst.left = 0;
140             mRectDst.top = 0;
141             mRectDst.right = viewWidth;
142             mRectDst.bottom = viewHeight;
143 
144             Log.d("ZoomImageView", "mRectSrc.top" + mRectSrc.top);
145             Log.d("ZoomImageView", "mRectSrc.bottom" + mRectSrc.bottom);
146             Log.d("ZoomImageView", "mRectSrc.left" + mRectSrc.left);
147             Log.d("ZoomImageView", "mRectSrc.right" + mRectSrc.right);
148 
149             Log.d("ZoomImageView", "mRectDst.top" + mRectDst.top);
150             Log.d("ZoomImageView", "mRectDst.bottom" + mRectDst.bottom);
151             Log.d("ZoomImageView", "mRectDst.left" + mRectDst.left);
152             Log.d("ZoomImageView", "mRectDst.right" + mRectDst.right);
153 
154             canvas.drawBitmap(mBitmap, mRectSrc, mRectDst, mPaint);
155         }
156     }
157 
158     @Override
159     protected void onLayout(boolean changed, int left, int top, int right,
160             int bottom) {
161         super.onLayout(changed, left, top, right, bottom);
162 
163         mAspectQuotient.updateAspectQuotient(right - left, bottom - top,
164                 mBitmap.getWidth(), mBitmap.getHeight());
165         mAspectQuotient.notifyObservers();
166     }
167 
168     @Override
169     public void update(Observable observable, Object data) {
170         invalidate();
171     }
172 
173     private class BasicZoomListener implements View.OnTouchListener {
174 
175         /** Zoom control to manipulate */
176         private BasicZoomControl mZoomControl;
177 
178         private float mFirstX = -1;
179         private float mFirstY = -1;
180         private float mSecondX = -1;
181         private float mSecondY = -1;
182 
183         private int mOldCounts = 0;
184 
185         /**
186          * Sets the zoom control to manipulate
187          * 
188          * @param control
189          *            Zoom control
190          */
191         public void setZoomControl(BasicZoomControl control) {
192             mZoomControl = control;
193         }
194 
195         public boolean onTouch(View v, MotionEvent event) {
196 
197             switch (event.getAction()) {
198             case MotionEvent.ACTION_DOWN:
199                 mOldCounts = 1;
200                 mFirstX = event.getX();
201                 mFirstY = event.getY();
202                 break;
203             case MotionEvent.ACTION_MOVE: {
204                 float fFirstX = event.getX();
205                 float fFirstY = event.getY();
206 
207                 int nCounts = event.getPointerCount();
208 
209                 if (1 == nCounts) {
210                     mOldCounts = 1;
211                     float dx = (fFirstX - mFirstX) / v.getWidth();
212                     float dy = (fFirstY - mFirstY) / v.getHeight();
213                     mZoomControl.pan(-dx, -dy);
214                 } else if (1 == mOldCounts) {
215                     mSecondX = event.getX(event.getPointerId(nCounts - 1));
216                     mSecondY = event.getY(event.getPointerId(nCounts - 1));
217                     mOldCounts = nCounts;
218                 } else {
219                     float fSecondX = event
220                             .getX(event.getPointerId(nCounts - 1));
221                     float fSecondY = event
222                             .getY(event.getPointerId(nCounts - 1));
223 
224                     double nLengthOld = getLength(mFirstX, mFirstY, mSecondX,
225                             mSecondY);
226                     double nLengthNow = getLength(fFirstX, fFirstY, fSecondX,
227                             fSecondY);
228 
229                     float d = (float) ((nLengthNow - nLengthOld) / v.getWidth());
230 
231                     mZoomControl.zoom((float) Math.pow(20, d),
232                             ((fFirstX + fSecondX) / 2 / v.getWidth()),
233                             ((fFirstY + fSecondY) / 2 / v.getHeight()));
234 
235                     mSecondX = fSecondX;
236                     mSecondY = fSecondY;
237                 }
238                 mFirstX = fFirstX;
239                 mFirstY = fFirstY;
240 
241                 break;
242             }
243 
244             }
245 
246             return true;
247         }
248 
249         private double getLength(float x1, float y1, float x2, float y2) {
250             return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
251         }
252     }
253 
254     private class BasicZoomControl implements Observer {
255 
256         /** Minimum zoom level limit */
257         private static final float MIN_ZOOM = 1;
258 
259         /** Maximum zoom level limit */
260         private static final float MAX_ZOOM = 16;
261 
262         /** Zoom state under control */
263         private final ZoomState mState = new ZoomState();
264 
265         /** Object holding aspect quotient of view and content */
266         private AspectQuotient mAspectQuotient;
267 
268         /**
269          * Set reference object holding aspect quotient
270          * 
271          * @param aspectQuotient
272          *            Object holding aspect quotient
273          */
274         public void setAspectQuotient(AspectQuotient aspectQuotient) {
275             if (mAspectQuotient != null) {
276                 mAspectQuotient.deleteObserver(this);
277             }
278 
279             mAspectQuotient = aspectQuotient;
280             mAspectQuotient.addObserver(this);
281         }
282 
283         /**
284          * Get zoom state being controlled
285          * 
286          * @return The zoom state
287          */
288         public ZoomState getZoomState() {
289             return mState;
290         }
291 
292         /**
293          * Zoom
294          * 
295          * @param f
296          *            Factor of zoom to apply
297          * @param x
298          *            X-coordinate of invariant position
299          * @param y
300          *            Y-coordinate of invariant position
301          */
302         public void zoom(float f, float x, float y) {
303 
304             // Log.d("Zoom", "zoom f = " + f);
305 
306             final float aspectQuotient = mAspectQuotient.get();
307 
308             final float prevZoomX = mState.getZoomX(aspectQuotient);
309             final float prevZoomY = mState.getZoomY(aspectQuotient);
310 
311             mState.setZoom(mState.getZoom() * f);
312             limitZoom();
313 
314             final float newZoomX = mState.getZoomX(aspectQuotient);
315             final float newZoomY = mState.getZoomY(aspectQuotient);
316 
317             // Pan to keep x and y coordinate invariant
318             mState.setPanX(mState.getPanX() + (x - .5f)
319                     * (1f / prevZoomX - 1f / newZoomX));
320             mState.setPanY(mState.getPanY() + (y - .5f)
321                     * (1f / prevZoomY - 1f / newZoomY));
322 
323             limitPan();
324 
325             mState.notifyObservers();
326         }
327 
328         /**
329          * Pan
330          * 
331          * @param dx
332          *            Amount to pan in x-dimension
333          * @param dy
334          *            Amount to pan in y-dimension
335          */
336         public void pan(float dx, float dy) {
337             final float aspectQuotient = mAspectQuotient.get();
338 
339             mState.setPanX(mState.getPanX() + dx
340                     / mState.getZoomX(aspectQuotient));
341             mState.setPanY(mState.getPanY() + dy
342                     / mState.getZoomY(aspectQuotient));
343 
344             limitPan();
345 
346             mState.notifyObservers();
347         }
348 
349         /**
350          * Help function to figure out max delta of pan from center position.
351          * 
352          * @param zoom
353          *            Zoom value
354          * @return Max delta of pan
355          */
356         private float getMaxPanDelta(float zoom) {
357             return Math.max(0f, .5f * ((zoom - 1) / zoom));
358         }
359 
360         /**
361          * Force zoom to stay within limits
362          */
363         private void limitZoom() {
364             if (mState.getZoom() < MIN_ZOOM) {
365                 mState.setZoom(MIN_ZOOM);
366             } else if (mState.getZoom() > MAX_ZOOM) {
367                 mState.setZoom(MAX_ZOOM);
368             }
369         }
370 
371         /**
372          * Force pan to stay within limits
373          */
374         private void limitPan() {
375             final float aspectQuotient = mAspectQuotient.get();
376 
377             final float zoomX = mState.getZoomX(aspectQuotient);
378             final float zoomY = mState.getZoomY(aspectQuotient);
379 
380             final float panMinX = .5f - getMaxPanDelta(zoomX);
381             final float panMaxX = .5f + getMaxPanDelta(zoomX);
382             final float panMinY = .5f - getMaxPanDelta(zoomY);
383             final float panMaxY = .5f + getMaxPanDelta(zoomY);
384 
385             if (mState.getPanX() < panMinX) {
386                 mState.setPanX(panMinX);
387             }
388             if (mState.getPanX() > panMaxX) {
389                 mState.setPanX(panMaxX);
390             }
391             if (mState.getPanY() < panMinY) {
392                 mState.setPanY(panMinY);
393             }
394             if (mState.getPanY() > panMaxY) {
395                 mState.setPanY(panMaxY);
396             }
397         }
398 
399         // Observable interface implementation
400 
401         public void update(Observable observable, Object data) {
402             limitZoom();
403             limitPan();
404         }
405     }
406 
407     private class AspectQuotient extends Observable {
408 
409         /**
410          * Aspect quotient
411          */
412         private float mAspectQuotient;
413 
414         // Public methods
415 
416         /**
417          * Gets aspect quotient
418          * 
419          * @return The aspect quotient
420          */
421         public float get() {
422             return mAspectQuotient;
423         }
424 
425         /**
426          * Updates and recalculates aspect quotient based on supplied view and
427          * content dimensions.
428          * 
429          * @param viewWidth
430          *            Width of view
431          * @param viewHeight
432          *            Height of view
433          * @param contentWidth
434          *            Width of content
435          * @param contentHeight
436          *            Height of content
437          */
438         public void updateAspectQuotient(float viewWidth, float viewHeight,
439                 float contentWidth, float contentHeight) {
440             final float aspectQuotient = (contentWidth / contentHeight)
441                     / (viewWidth / viewHeight);
442 
443             if (aspectQuotient != mAspectQuotient) {
444                 mAspectQuotient = aspectQuotient;
445                 setChanged();
446             }
447         }
448     }
449 
450     private class ZoomState extends Observable {
451         /**
452          * Zoom level A value of 1.0 means the content fits the view.
453          */
454         private float mZoom;
455 
456         /**
457          * Pan position x-coordinate X-coordinate of zoom window center
458          * position, relative to the width of the content.
459          */
460         private float mPanX;
461 
462         /**
463          * Pan position y-coordinate Y-coordinate of zoom window center
464          * position, relative to the height of the content.
465          */
466         private float mPanY;
467 
468         // Public methods
469 
470         /**
471          * Get current x-pan
472          * 
473          * @return current x-pan
474          */
475         public float getPanX() {
476             return mPanX;
477         }
478 
479         /**
480          * Get current y-pan
481          * 
482          * @return Current y-pan
483          */
484         public float getPanY() {
485             return mPanY;
486         }
487 
488         /**
489          * Get current zoom value
490          * 
491          * @return Current zoom value
492          */
493         public float getZoom() {
494             return mZoom;
495         }
496 
497         /**
498          * Help function for calculating current zoom value in x-dimension
499          * 
500          * @param aspectQuotient
501          *            (Aspect ratio content) / (Aspect ratio view)
502          * @return Current zoom value in x-dimension
503          */
504         public float getZoomX(float aspectQuotient) {
505             return Math.min(mZoom, mZoom * aspectQuotient);
506         }
507 
508         /**
509          * Help function for calculating current zoom value in y-dimension
510          * 
511          * @param aspectQuotient
512          *            (Aspect ratio content) / (Aspect ratio view)
513          * @return Current zoom value in y-dimension
514          */
515         public float getZoomY(float aspectQuotient) {
516             return Math.min(mZoom, mZoom / aspectQuotient);
517         }
518 
519         /**
520          * Set pan-x
521          * 
522          * @param panX
523          *            Pan-x value to set
524          */
525         public void setPanX(float panX) {
526             if (panX != mPanX) {
527                 mPanX = panX;
528                 setChanged();
529             }
530         }
531 
532         /**
533          * Set pan-y
534          * 
535          * @param panY
536          *            Pan-y value to set
537          */
538         public void setPanY(float panY) {
539             if (panY != mPanY) {
540                 mPanY = panY;
541                 setChanged();
542             }
543         }
544 
545         /**
546          * Set zoom
547          * 
548          * @param zoom
549          *            Zoom value to set
550          */
551         public void setZoom(float zoom) {
552             if (zoom != mZoom) {
553                 mZoom = zoom;
554                 setChanged();
555             }
556         }
557     }
558 }

布局修改:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6 
 7   <!-- 引用自定义控件 -->
 8     <com.example.imagezoomdemo.zoomimage
 9         android:id="@+id/image"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content" >
12     </com.example.imagezoomdemo.zoomimage>
13 
14 </LinearLayout>

最后修改下Activity:

 1 package com.example.imagezoomdemo;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.graphics.Bitmap;
 6 import android.graphics.BitmapFactory;
 7  
 8 public class MainActivity extends Activity {
 9 
10      private zoomimage zoomImg;
11      
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16         
17          zoomImg = (zoomimage) findViewById(R.id.image);
18             Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),
19                     R.drawable.aa);
20             zoomImg.setImage(bitmap);
21     }
22 
23 }

运行效果:

(1)原图:

(2) 放大:

(3) 缩小

转载于:https://www.cnblogs.com/benchao/p/5258765.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值