学习安卓手势滑动,多点触摸放大缩小图片,分享给大家供大家参考,具体代码如下
1.布局文件如下main.xml
<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:layout_wIDth="fill_parent" androID:layout_height="fill_parent" androID:orIEntation="vertical" > <!-- 引用自定义控件 --> <com.ymw.zoomimage.ZoomImageVIEw androID:ID="@+ID/image" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" > </com.ymw.zoomimage.ZoomImageVIEw></linearLayout>
2.自定义缩放图片控件ZoomImageVIEw.java代码:
package com.ymw.zoomimage;import java.util.Observable;import java.util.Observer;import androID.content.Context;import androID.graphics.Bitmap;import androID.graphics.Canvas;import androID.graphics.Paint;import androID.graphics.Rect;import androID.util.AttributeSet;import androID.util.Log;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;public class ZoomImageVIEw extends VIEw implements Observer { /** Paint object used when drawing bitmap. */ private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); /** Rectangle used (and re-used) for cropPing source image. */ private final Rect mRectSrc = new Rect(); /** Rectangle used (and re-used) for specifying drawing area on canvas. */ private final Rect mRectDst = new Rect(); /** Object holding aspect quotIEnt */ private final AspectQuotIEnt mAspectQuotIEnt = new AspectQuotIEnt(); /** The bitmap that we're zooming in,and drawing on the screen. */ private Bitmap mBitmap; /** State of the zoom. */ private ZoomState mState; private BasicZoomControl mZoomControl; private BasicZoomListener mZoomListener; public ZoomImageVIEw(Context context,AttributeSet attrs) { super(context,attrs); mZoomControl = new BasicZoomControl(); mZoomListener = new BasicZoomListener(); mZoomListener.setZoomControl(mZoomControl); setZoomState(mZoomControl.getZoomState()); setontouchListener(mZoomListener); mZoomControl.setAspectQuotIEnt(getAspectQuotIEnt()); } public voID zoomImage(float f,float x,float y) { mZoomControl.zoom(f,x,y); } public voID setimage(Bitmap bitmap) { mBitmap = bitmap; mAspectQuotIEnt.updateAspectQuotIEnt(getWIDth(),getHeight(),mBitmap.getWIDth(),mBitmap.getHeight()); mAspectQuotIEnt.notifyObservers(); invalIDate(); } private voID setZoomState(ZoomState state) { if (mState != null) { mState.deleteObserver(this); } mState = state; mState.addobserver(this); invalIDate(); } private AspectQuotIEnt getAspectQuotIEnt() { return mAspectQuotIEnt; } @OverrIDe protected voID onDraw(Canvas canvas) { if (mBitmap != null && mState != null) { Log.d("ZoomImageVIEw","OnDraw"); final float aspectQuotIEnt = mAspectQuotIEnt.get(); final int vIEwWIDth = getWIDth(); final int vIEwHeight = getHeight(); final int bitmapWIDth = mBitmap.getWIDth(); final int bitmapHeight = mBitmap.getHeight(); Log.d("ZoomImageVIEw","vIEwWIDth = " + vIEwWIDth); Log.d("ZoomImageVIEw","vIEwHeight = " + vIEwHeight); Log.d("ZoomImageVIEw","bitmapWIDth = " + bitmapWIDth); Log.d("ZoomImageVIEw","bitmapHeight = " + bitmapHeight); final float panX = mState.getPanX(); final float panY = mState.getPanY(); final float zoomX = mState.getZoomX(aspectQuotIEnt) * vIEwWIDth / bitmapWIDth; final float zoomY = mState.getZoomY(aspectQuotIEnt) * vIEwHeight / bitmapHeight; // Setup source and destination rectangles mRectSrc.left = (int) (panX * bitmapWIDth - vIEwWIDth / (zoomX * 2)); mRectSrc.top = (int) (panY * bitmapHeight - vIEwHeight / (zoomY * 2)); mRectSrc.right = (int) (mRectSrc.left + vIEwWIDth / zoomX); mRectSrc.bottom = (int) (mRectSrc.top + vIEwHeight / zoomY); // mRectDst.left = getleft(); mRectDst.left = 0; mRectDst.top = 0; // mRectDst.right = getRight(); mRectDst.right = getWIDth(); mRectDst.bottom = getHeight(); // Adjust source rectangle so that it fits within the source image. if (mRectSrc.left < 0) { mRectDst.left += -mRectSrc.left * zoomX; mRectSrc.left = 0; } if (mRectSrc.right > bitmapWIDth) { mRectDst.right -= (mRectSrc.right - bitmapWIDth) * zoomX; mRectSrc.right = bitmapWIDth; } if (mRectSrc.top < 0) { mRectDst.top += -mRectSrc.top * zoomY; mRectSrc.top = 0; } if (mRectSrc.bottom > bitmapHeight) { mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY; mRectSrc.bottom = bitmapHeight; } mRectDst.left = 0; mRectDst.top = 0; mRectDst.right = vIEwWIDth; mRectDst.bottom = vIEwHeight; Log.d("ZoomImageVIEw","mRectSrc.top" + mRectSrc.top); Log.d("ZoomImageVIEw","mRectSrc.bottom" + mRectSrc.bottom); Log.d("ZoomImageVIEw","mRectSrc.left" + mRectSrc.left); Log.d("ZoomImageVIEw","mRectSrc.right" + mRectSrc.right); Log.d("ZoomImageVIEw","mRectDst.top" + mRectDst.top); Log.d("ZoomImageVIEw","mRectDst.bottom" + mRectDst.bottom); Log.d("ZoomImageVIEw","mRectDst.left" + mRectDst.left); Log.d("ZoomImageVIEw","mRectDst.right" + mRectDst.right); canvas.drawBitmap(mBitmap,mRectSrc,mRectDst,mPaint); } } @OverrIDe protected voID onLayout(boolean changed,int left,int top,int right,int bottom) { super.onLayout(changed,left,top,right,bottom); mAspectQuotIEnt.updateAspectQuotIEnt(right - left,bottom - top,mBitmap.getHeight()); mAspectQuotIEnt.notifyObservers(); } @OverrIDe public voID update(Observable observable,Object data) { invalIDate(); } private class BasicZoomListener implements VIEw.OntouchListener { /** Zoom control to manipulate */ private BasicZoomControl mZoomControl; private float mFirstX = -1; private float mFirstY = -1; private float mSecondX = -1; private float mSecondY = -1; private int moldCounts = 0; /** * Sets the zoom control to manipulate * * @param control * Zoom control */ public voID setZoomControl(BasicZoomControl control) { mZoomControl = control; } public boolean ontouch(VIEw v,MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: moldCounts = 1; mFirstX = event.getX(); mFirstY = event.getY(); break; case MotionEvent.ACTION_MOVE: { float fFirstX = event.getX(); float fFirstY = event.getY(); int nCounts = event.getPointerCount(); if (1 == nCounts) { moldCounts = 1; float dx = (fFirstX - mFirstX) / v.getWIDth(); float dy = (fFirstY - mFirstY) / v.getHeight(); mZoomControl.pan(-dx,-dy); } else if (1 == moldCounts) { mSecondX = event.getX(event.getPointerID(nCounts - 1)); mSecondY = event.getY(event.getPointerID(nCounts - 1)); moldCounts = nCounts; } else { float fSecondX = event .getX(event.getPointerID(nCounts - 1)); float fSecondY = event .getY(event.getPointerID(nCounts - 1)); double nLengthold = getLength(mFirstX,mFirstY,mSecondX,mSecondY); double nLengthNow = getLength(fFirstX,fFirstY,fSecondX,fSecondY); float d = (float) ((nLengthNow - nLengthold) / v.getWIDth()); mZoomControl.zoom((float) Math.pow(20,d),((fFirstX + fSecondX) / 2 / v.getWIDth()),((fFirstY + fSecondY) / 2 / v.getHeight())); mSecondX = fSecondX; mSecondY = fSecondY; } mFirstX = fFirstX; mFirstY = fFirstY; break; } } return true; } private double getLength(float x1,float y1,float x2,float y2) { return Math.sqrt(Math.pow(x1 - x2,2) + Math.pow(y1 - y2,2)); } } private class BasicZoomControl implements Observer { /** Minimum zoom level limit */ private static final float MIN_ZOOM = 1; /** Maximum zoom level limit */ private static final float MAX_ZOOM = 16; /** Zoom state under control */ private final ZoomState mState = new ZoomState(); /** Object holding aspect quotIEnt of vIEw and content */ private AspectQuotIEnt mAspectQuotIEnt; /** * Set reference object holding aspect quotIEnt * * @param aspectQuotIEnt * Object holding aspect quotIEnt */ public voID setAspectQuotIEnt(AspectQuotIEnt aspectQuotIEnt) { if (mAspectQuotIEnt != null) { mAspectQuotIEnt.deleteObserver(this); } mAspectQuotIEnt = aspectQuotIEnt; mAspectQuotIEnt.addobserver(this); } /** * Get zoom state being controlled * * @return The zoom state */ public ZoomState getZoomState() { return mState; } /** * Zoom * * @param f * Factor of zoom to apply * @param x * X-coordinate of invariant position * @param y * Y-coordinate of invariant position */ public voID zoom(float f,float y) { // Log.d("Zoom","zoom f = " + f); final float aspectQuotIEnt = mAspectQuotIEnt.get(); final float prevZoomX = mState.getZoomX(aspectQuotIEnt); final float prevZoomY = mState.getZoomY(aspectQuotIEnt); mState.setZoom(mState.getZoom() * f); limitZoom(); final float newZoomX = mState.getZoomX(aspectQuotIEnt); final float newZoomY = mState.getZoomY(aspectQuotIEnt); // Pan to keep x and y coordinate invariant mState.setPanX(mState.getPanX() + (x - .5f) * (1f / prevZoomX - 1f / newZoomX)); mState.setPanY(mState.getPanY() + (y - .5f) * (1f / prevZoomY - 1f / newZoomY)); limitPan(); mState.notifyObservers(); } /** * Pan * * @param dx * Amount to pan in x-dimension * @param dy * Amount to pan in y-dimension */ public voID pan(float dx,float dy) { final float aspectQuotIEnt = mAspectQuotIEnt.get(); mState.setPanX(mState.getPanX() + dx / mState.getZoomX(aspectQuotIEnt)); mState.setPanY(mState.getPanY() + dy / mState.getZoomY(aspectQuotIEnt)); limitPan(); mState.notifyObservers(); } /** * Help function to figure out max delta of pan from center position. * * @param zoom * Zoom value * @return Max delta of pan */ private float getMaxPanDelta(float zoom) { return Math.max(0f,.5f * ((zoom - 1) / zoom)); } /** * Force zoom to stay within limits */ private voID limitZoom() { if (mState.getZoom() < MIN_ZOOM) { mState.setZoom(MIN_ZOOM); } else if (mState.getZoom() > MAX_ZOOM) { mState.setZoom(MAX_ZOOM); } } /** * Force pan to stay within limits */ private voID limitPan() { final float aspectQuotIEnt = mAspectQuotIEnt.get(); final float zoomX = mState.getZoomX(aspectQuotIEnt); final float zoomY = mState.getZoomY(aspectQuotIEnt); final float panMinX = .5f - getMaxPanDelta(zoomX); final float panMaxX = .5f + getMaxPanDelta(zoomX); final float panMinY = .5f - getMaxPanDelta(zoomY); final float panMaxY = .5f + getMaxPanDelta(zoomY); if (mState.getPanX() < panMinX) { mState.setPanX(panMinX); } if (mState.getPanX() > panMaxX) { mState.setPanX(panMaxX); } if (mState.getPanY() < panMinY) { mState.setPanY(panMinY); } if (mState.getPanY() > panMaxY) { mState.setPanY(panMaxY); } } // Observable interface implementation public voID update(Observable observable,Object data) { limitZoom(); limitPan(); } } private class AspectQuotIEnt extends Observable { /** * Aspect quotIEnt */ private float mAspectQuotIEnt; // Public methods /** * Gets aspect quotIEnt * * @return The aspect quotIEnt */ public float get() { return mAspectQuotIEnt; } /** * Updates and recalculates aspect quotIEnt based on supplIEd vIEw and * content dimensions. * * @param vIEwWIDth * WIDth of vIEw * @param vIEwHeight * Height of vIEw * @param contentWIDth * WIDth of content * @param contentHeight * Height of content */ public voID updateAspectQuotIEnt(float vIEwWIDth,float vIEwHeight,float contentWIDth,float contentHeight) { final float aspectQuotIEnt = (contentWIDth / contentHeight) / (vIEwWIDth / vIEwHeight); if (aspectQuotIEnt != mAspectQuotIEnt) { mAspectQuotIEnt = aspectQuotIEnt; setChanged(); } } } private class ZoomState extends Observable { /** * Zoom level A value of 1.0 means the content fits the vIEw. */ private float mZoom; /** * Pan position x-coordinate X-coordinate of zoom window center * position,relative to the wIDth of the content. */ private float mPanX; /** * Pan position y-coordinate Y-coordinate of zoom window center * position,relative to the height of the content. */ private float mPanY; // Public methods /** * Get current x-pan * * @return current x-pan */ public float getPanX() { return mPanX; } /** * Get current y-pan * * @return Current y-pan */ public float getPanY() { return mPanY; } /** * Get current zoom value * * @return Current zoom value */ public float getZoom() { return mZoom; } /** * Help function for calculating current zoom value in x-dimension * * @param aspectQuotIEnt * (Aspect ratio content) / (Aspect ratio vIEw) * @return Current zoom value in x-dimension */ public float getZoomX(float aspectQuotIEnt) { return Math.min(mZoom,mZoom * aspectQuotIEnt); } /** * Help function for calculating current zoom value in y-dimension * * @param aspectQuotIEnt * (Aspect ratio content) / (Aspect ratio vIEw) * @return Current zoom value in y-dimension */ public float getZoomY(float aspectQuotIEnt) { return Math.min(mZoom,mZoom / aspectQuotIEnt); } /** * Set pan-x * * @param panX * Pan-x value to set */ public voID setPanX(float panX) { if (panX != mPanX) { mPanX = panX; setChanged(); } } /** * Set pan-y * * @param panY * Pan-y value to set */ public voID setPanY(float panY) { if (panY != mPanY) { mPanY = panY; setChanged(); } } /** * Set zoom * * @param zoom * Zoom value to set */ public voID setZoom(float zoom) { if (zoom != mZoom) { mZoom = zoom; setChanged(); } } }}
3.工程主文件MainActivity.java代码:
package com.ymw.zoomimage;import androID.app.Activity;import androID.graphics.Bitmap;import androID.graphics.BitmapFactory;import androID.os.Bundle;public class MainActivity extends Activity { private ZoomImageVIEw zoomimg; @OverrIDe public voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.main); zoomimg = (ZoomImageVIEw) findVIEwByID(R.ID.image); Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.a); zoomimg.setimage(bitmap); }}
以上就是AndroID多点触摸放大缩小图片的示例代码,希望对大家的学习有所帮助。
总结以上是内存溢出为你收集整理的Android手势滑动实现两点触摸缩放图片全部内容,希望文章能够帮你解决Android手势滑动实现两点触摸缩放图片所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)