android zoom,Android ImageView Zoom-in and Zoom-Out

The other implementations here all have some kind of a flaw. so i basically mixed them up and came up with this.

Create a custom view like this:

ZoomableImageView.java:

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Matrix;

import android.graphics.PointF;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.ScaleGestureDetector;

import android.view.View;

import android.widget.ImageView;

public class ZoomableImageView extends ImageView

{

Matrix matrix = new Matrix();

static final int NONE = 0;

static final int DRAG = 1;

static final int ZOOM = 2;

static final int CLICK = 3;

int mode = NONE;

PointF last = new PointF();

PointF start = new PointF();

float minScale = 1f;

float maxScale = 4f;

float[] m;

float redundantXSpace, redundantYSpace;

float width, height;

float saveScale = 1f;

float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

ScaleGestureDetector mScaleDetector;

Context context;

public ZoomableImageView(Context context, AttributeSet attr)

{

super(context, attr);

super.setClickable(true);

this.context = context;

mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

matrix.setTranslate(1f, 1f);

m = new float[9];

setImageMatrix(matrix);

setScaleType(ScaleType.MATRIX);

setOnTouchListener(new OnTouchListener()

{

@Override

public boolean onTouch(View v, MotionEvent event)

{

mScaleDetector.onTouchEvent(event);

matrix.getValues(m);

float x = m[Matrix.MTRANS_X];

float y = m[Matrix.MTRANS_Y];

PointF curr = new PointF(event.getX(), event.getY());

switch (event.getAction())

{

//when one finger is touching

//set the mode to DRAG

case MotionEvent.ACTION_DOWN:

last.set(event.getX(), event.getY());

start.set(last);

mode = DRAG;

break;

//when two fingers are touching

//set the mode to ZOOM

case MotionEvent.ACTION_POINTER_DOWN:

last.set(event.getX(), event.getY());

start.set(last);

mode = ZOOM;

break;

//when a finger moves

//If mode is applicable move image

case MotionEvent.ACTION_MOVE:

//if the mode is ZOOM or

//if the mode is DRAG and already zoomed

if (mode == ZOOM || (mode == DRAG && saveScale > minScale))

{

float deltaX = curr.x - last.x;// x difference

float deltaY = curr.y - last.y;// y difference

float scaleWidth = Math.round(origWidth * saveScale);// width after applying current scale

float scaleHeight = Math.round(origHeight * saveScale);// height after applying current scale

//if scaleWidth is smaller than the views width

//in other words if the image width fits in the view

//limit left and right movement

if (scaleWidth < width)

{

deltaX = 0;

if (y + deltaY > 0)

deltaY = -y;

else if (y + deltaY < -bottom)

deltaY = -(y + bottom);

}

//if scaleHeight is smaller than the views height

//in other words if the image height fits in the view

//limit up and down movement

else if (scaleHeight < height)

{

deltaY = 0;

if (x + deltaX > 0)

deltaX = -x;

else if (x + deltaX < -right)

deltaX = -(x + right);

}

//if the image doesnt fit in the width or height

//limit both up and down and left and right

else

{

if (x + deltaX > 0)

deltaX = -x;

else if (x + deltaX < -right)

deltaX = -(x + right);

if (y + deltaY > 0)

deltaY = -y;

else if (y + deltaY < -bottom)

deltaY = -(y + bottom);

}

//move the image with the matrix

matrix.postTranslate(deltaX, deltaY);

//set the last touch location to the current

last.set(curr.x, curr.y);

}

break;

//first finger is lifted

case MotionEvent.ACTION_UP:

mode = NONE;

int xDiff = (int) Math.abs(curr.x - start.x);

int yDiff = (int) Math.abs(curr.y - start.y);

if (xDiff < CLICK && yDiff < CLICK)

performClick();

break;

// second finger is lifted

case MotionEvent.ACTION_POINTER_UP:

mode = NONE;

break;

}

setImageMatrix(matrix);

invalidate();

return true;

}

});

}

@Override

public void setImageBitmap(Bitmap bm)

{

super.setImageBitmap(bm);

bmWidth = bm.getWidth();

bmHeight = bm.getHeight();

}

public void setMaxZoom(float x)

{

maxScale = x;

}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener

{

@Override

public boolean onScaleBegin(ScaleGestureDetector detector)

{

mode = ZOOM;

return true;

}

@Override

public boolean onScale(ScaleGestureDetector detector)

{

float mScaleFactor = detector.getScaleFactor();

float origScale = saveScale;

saveScale *= mScaleFactor;

if (saveScale > maxScale)

{

saveScale = maxScale;

mScaleFactor = maxScale / origScale;

}

else if (saveScale < minScale)

{

saveScale = minScale;

mScaleFactor = minScale / origScale;

}

right = width * saveScale - width - (2 * redundantXSpace * saveScale);

bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);

if (origWidth * saveScale <= width || origHeight * saveScale <= height)

{

matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);

if (mScaleFactor < 1)

{

matrix.getValues(m);

float x = m[Matrix.MTRANS_X];

float y = m[Matrix.MTRANS_Y];

if (mScaleFactor < 1)

{

if (Math.round(origWidth * saveScale) < width)

{

if (y < -bottom)

matrix.postTranslate(0, -(y + bottom));

else if (y > 0)

matrix.postTranslate(0, -y);

}

else

{

if (x < -right)

matrix.postTranslate(-(x + right), 0);

else if (x > 0)

matrix.postTranslate(-x, 0);

}

}

}

}

else

{

matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());

matrix.getValues(m);

float x = m[Matrix.MTRANS_X];

float y = m[Matrix.MTRANS_Y];

if (mScaleFactor < 1) {

if (x < -right)

matrix.postTranslate(-(x + right), 0);

else if (x > 0)

matrix.postTranslate(-x, 0);

if (y < -bottom)

matrix.postTranslate(0, -(y + bottom));

else if (y > 0)

matrix.postTranslate(0, -y);

}

}

return true;

}

}

@Override

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

{

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = MeasureSpec.getSize(widthMeasureSpec);

height = MeasureSpec.getSize(heightMeasureSpec);

//Fit to screen.

float scale;

float scaleX = width / bmWidth;

float scaleY = height / bmHeight;

scale = Math.min(scaleX, scaleY);

matrix.setScale(scale, scale);

setImageMatrix(matrix);

saveScale = 1f;

// Center the image

redundantYSpace = height - (scale * bmHeight) ;

redundantXSpace = width - (scale * bmWidth);

redundantYSpace /= 2;

redundantXSpace /= 2;

matrix.postTranslate(redundantXSpace, redundantYSpace);

origWidth = width - 2 * redundantXSpace;

origHeight = height - 2 * redundantYSpace;

right = width * saveScale - width - (2 * redundantXSpace * saveScale);

bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);

setImageMatrix(matrix);

}

}

Then add the image like this:

ZoomableImageView touch = (ZoomableImageView)findViewById(R.id.IMAGEID);

touch.setImageBitmap(bitmap);

Add the view like this in XML:

android:id="@+id/IMAGEID"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值