一、自定义imageview的实现,实现了放大与缩小.
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); ZoomState()); setOnTouchListener(mZoomListener); mZoomControl.setAspectQuotient(getAspectQuotient()); }public void zoomImage(float f, float x, float y) {(f, x, y); }public void setImage(Bitmap bitmap) {mBitmap = bitmap; try {mAspectQuotient.updateAspectQuotient(getWidth(), getHeight(), Width(), Height()); }catch (Exception e){e.printStackTrace(); }ifyObservers(); 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 = (); final int viewWidth = getWidth(); final int viewHeight = getHeight(); final int bitmapWidth = Width(); final int bitmapHeight = Height(); Log.d("ZoomImageView", "viewWidth = " + viewWidth); Log.d("ZoomImageView", "viewHeight = " + viewHeight); Log.d("ZoomImageView", "bitmapWidth = " + bitmapWidth); Log.d("ZoomImageView", "bitmapHeight = " + bitmapHeight); final float panX = PanX(); final float panY = PanY(); final float zoomX = ZoomX(aspectQuotient) * viewWidth/ bitmapWidth; final float zoomY = ZoomY(aspectQuotient) * viewHeight/ bitmapHeight; // Setup source and destination rectangles mRectSrc.left = (int) (panX * bitmapWidth - viewWidth / (zoomX * 2)); p = (int) (panY * bitmapHeight - viewHeight/ (zoomY * 2)); mRectSrc.right = (int) (mRectSrc.left + viewWidth / zoomX); mRectSrc.bottom = (int) (p + viewHeight / zoomY); // mRectDst.left = getLeft(); mRectDst.left = 0; p = 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 (p < 0) {p += -p * zoomY; p = 0; }if (mRectSrc.bottom > bitmapHeight) {mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY; mRectSrc.bottom = bitmapHeight; }mRectDst.left = 0; p = 0; mRectDst.right = viewWidth; mRectDst.bottom = viewHeight; Log.d("ZoomImageView", p" + p); Log.d("ZoomImageView", "mRectSrc.bottom" + mRectSrc.bottom); Log.d("ZoomImageView", "mRectSrc.left" + mRectSrc.left); Log.d("ZoomImageView", "mRectSrc.right" + mRectSrc.right); Log.d("ZoomImageView", p" + p); 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) {Layout(changed, left, top, right, bottom); try {mAspectQuotient.updateAspectQuotient(right - left, bottom - top, Width(), Height()); }catch (Exception e){e.printStackTrace(); }ifyObservers(); }@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 (Action()) {case MotionEvent.ACTION_DOWN:mOldCounts = 1; mFirstX = X(); mFirstY = Y(); break; case MotionEvent.ACTION_MOVE: {float fFirstX = X(); float fFirstY = Y(); int nCounts = PointerCount(); 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 = PointerId(nCounts - 1)); mSecondY = PointerId(nCounts - 1)); mOldCounts = nCounts; } else {float fSecondX = PointerId(nCounts - 1)); float fSecondY = PointerId(nCounts - 1)); double nLengthOld = getLength(mFirstX, mFirstY, mSecondX, mSecondY); double nLengthNow = getLength(fFirstX, fFirstY, fSecondX, fSecondY); float d = (float) ((nLengthNow - nLengthOld) / v.getWidth()); ((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 x, float y) {// Log.d("Zoom", "zoom f = " + f); final float aspectQuotient = (); final float prevZoomX = ZoomX(aspectQuotient); final float prevZoomY = ZoomY(aspectQuotient); mState.Zoom() * f); limitZoom(); final float newZoomX = ZoomX(aspectQuotient); final float newZoomY = ZoomY(aspectQuotient); // Pan to keep x and y coordinate invariant mState.PanX() + (x - .5f)* (1f / prevZoomX - 1f / newZoomX)); mState.PanY() + (y - .5f)* (1f / prevZoomY - 1f / newZoomY)); limitPan(); ifyObservers(); }/** * 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 = (); mState.PanX() + dx/ ZoomX(aspectQuotient)); mState.PanY() + dy/ ZoomY(aspectQuotient)); limitPan(); ifyObservers(); }/** * 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 (Zoom() < MIN_ZOOM) {mState.setZoom(MIN_ZOOM); } else if (Zoom() > MAX_ZOOM) {mState.setZoom(MAX_ZOOM); }}/** * Force pan to stay within limits */ private void limitPan() {final float aspectQuotient = (); final float zoomX = ZoomX(aspectQuotient); final float zoomY = ZoomY(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 (PanX() < panMinX) {mState.setPanX(panMinX); }if (PanX() > panMaxX) {mState.setPanX(panMaxX); }if (PanY() < panMinY) {mState.setPanY(panMinY); }if (PanY() > 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(); }}} }
要使用这个自定义view,就在配置文件中定义,显示的方法就是setImage(bitmap);ZoomImageView iv = new ZoomImageView(this,null); Bitmap bitmap = BitmapUtil.lessenUriImage(this,imageurl); iv.setImage(bitmap);
本文发布于:2024-02-04 11:52:55,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170706554455312.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |