Android实现手势控制ImageView图片大小

本文实例实现的主要功能是在ImageView中识别手势用以控制图片放大或缩小,具有一定的参考价值,分享给大家。

public class MatrixImageView extends ImageView {

private GestureDetector mGestureDetector;

private Matrix mMatrix = new Matrix();

private float mImageWidth;

private float mImageHeight;

private float mScale;

private OnMovingListener mMoveListener;

private OnSingleTapListener mSingleTapListener;

public MatrixImageView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public MatrixImageView(Context context) {

super(context, null);

init();

}

private void init() {

MatrixTouchListener listener = new MatrixTouchListener();

setOnTouchListener(listener);

mGestureDetector = new GestureDetector(getContext(),

new GestureListener(listener));

setBackgroundColor(Color.BLACK);

setScaleType(ScaleType.FIT_CENTER);

}

public void setOnMovingListener(OnMovingListener listener) {

mMoveListener = listener;

}

public void setOnSingleTapListener(OnSingleTapListener onSingleTapListener) {

this.mSingleTapListener = onSingleTapListener;

}

@Override

public void setImageBitmap(Bitmap bm) {

super.setImageBitmap(bm);

if (getWidth() == 0) {

ViewTreeObserver vto = getViewTreeObserver();

vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

public boolean onPreDraw() {

initData();

MatrixImageView.this.getViewTreeObserver()

.removeOnPreDrawListener(this);

return true;

}

});

} else {

initData();

}

}

private void initData() {

mMatrix.set(getImageMatrix());

float[] values = new float[9];

mMatrix.getValues(values);

mImageWidth = getWidth() / values[Matrix.MSCALE_X];

mImageHeight = (getHeight() - values[Matrix.MTRANS_Y] * 2)

/ values[Matrix.MSCALE_Y];

mScale = values[Matrix.MSCALE_X];

}

public class MatrixTouchListener implements OnTouchListener {

private static final int MODE_DRAG = 1;

private static final int MODE_ZOOM = 2;

private static final int MODE_UNABLE = 3;

private static final float MAX_SCALE = 6;

private static final float DOUBLE_CLICK_SACLE = 2;

private int mMode = 0;

private float mStartDis;

private Matrix mCurrentMatrix = new Matrix();

private boolean mLeftDragable;

private boolean mRightDragable;

private boolean mFirstMove = false;

private PointF mStartPoint = new PointF();

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getActionMasked()) {

case MotionEvent.ACTION_DOWN:

mMode = MODE_DRAG;

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

isMatrixEnable();

startDrag();

checkDragable();

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

reSetMatrix();

stopDrag();

break;

case MotionEvent.ACTION_MOVE:

if (mMode == MODE_ZOOM) {

setZoomMatrix(event);

} else if (mMode == MODE_DRAG) {

setDragMatrix(event);

} else {

stopDrag();

}

break;

case MotionEvent.ACTION_POINTER_DOWN:

if (mMode == MODE_UNABLE)

return true;

mMode = MODE_ZOOM;

mStartDis = distance(event);

break;

case MotionEvent.ACTION_POINTER_UP:

break;

default:

break;

}

return mGestureDetector.onTouchEvent(event);

}

private void startDrag() {

if (mMoveListener != null)

mMoveListener.startDrag();

}

private void stopDrag() {

if (mMoveListener != null)

mMoveListener.stopDrag();

}

private void checkDragable() {

mLeftDragable = true;

mRightDragable = true;

mFirstMove = true;

float[] values = new float[9];

getImageMatrix().getValues(values);

if (values[Matrix.MTRANS_X] >= 0)

mRightDragable = false;

if ((mImageWidth) * values[Matrix.MSCALE_X]

+ values[Matrix.MTRANS_X] <= getWidth()) {

mLeftDragable = false;

}

}

public void setDragMatrix(MotionEvent event) {

if (isZoomChanged()) {

float dx = event.getX() - mStartPoint.x;

float dy = event.getY() - mStartPoint.y;

if (Math.sqrt(dx * dx + dy * dy) > 10f) {

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

mCurrentMatrix.set(getImageMatrix());

float[] values = new float[9];

mCurrentMatrix.getValues(values);

dy = checkDyBound(values, dy);

dx = checkDxBound(values, dx, dy);

mCurrentMatrix.postTranslate(dx, dy);

setImageMatrix(mCurrentMatrix);

}

} else {

stopDrag();

}

}

private boolean isZoomChanged() {

float[] values = new float[9];

getImageMatrix().getValues(values);

float scale = values[Matrix.MSCALE_X];

return scale != mScale;

}

private float checkDyBound(float[] values, float dy) {

float height = getHeight();

if (mImageHeight * values[Matrix.MSCALE_Y] < height)

return 0;

if (values[Matrix.MTRANS_Y] + dy > 0)

dy = -values[Matrix.MTRANS_Y];

else if (values[Matrix.MTRANS_Y] + dy < -(mImageHeight

* values[Matrix.MSCALE_Y] - height))

dy = -(mImageHeight * values[Matrix.MSCALE_Y] - height)

- values[Matrix.MTRANS_Y];

return dy;

}

private float checkDxBound(float[] values, float dx, float dy) {

float width = getWidth();

if (!mLeftDragable && dx < 0) {

if (Math.abs(dx) * 0.4f > Math.abs(dy) && mFirstMove) {

stopDrag();

}

return 0;

}

if (!mRightDragable && dx > 0) {

if (Math.abs(dx) * 0.4f > Math.abs(dy) && mFirstMove) {

stopDrag();

}

return 0;

}

mLeftDragable = true;

mRightDragable = true;

if (mFirstMove)

mFirstMove = false;

if (mImageWidth * values[Matrix.MSCALE_X] < width) {

return 0;

}

if (values[Matrix.MTRANS_X] + dx > 0) {

dx = -values[Matrix.MTRANS_X];

} else if (values[Matrix.MTRANS_X] + dx < -(mImageWidth

* values[Matrix.MSCALE_X] - width)) {

dx = -(mImageWidth * values[Matrix.MSCALE_X] - width)

- values[Matrix.MTRANS_X];

}

return dx;

}

private void setZoomMatrix(MotionEvent event) {

if (event.getPointerCount() < 2)

return;

float endDis = distance(event);

if (endDis > 10f) {

float scale = endDis / mStartDis;

mStartDis = endDis;

mCurrentMatrix.set(getImageMatrix());

float[] values = new float[9];

mCurrentMatrix.getValues(values);

scale = checkMaxScale(scale, values);

PointF centerF = getCenter(scale, values);

mCurrentMatrix.postScale(scale, scale, centerF.x, centerF.y);

setImageMatrix(mCurrentMatrix);

}

}

private PointF getCenter(float scale, float[] values) {

if (scale * values[Matrix.MSCALE_X] < mScale || scale >= 1) {

return new PointF(getWidth() / 2, getHeight() / 2);

}

float cx = getWidth() / 2;

float cy = getHeight() / 2;

if ((getWidth() / 2 - values[Matrix.MTRANS_X]) * scale < getWidth() / 2)

cx = 0;

if ((mImageWidth * values[Matrix.MSCALE_X] + values[Matrix.MTRANS_X])

* scale < getWidth())

cx = getWidth();

return new PointF(cx, cy);

}

private float checkMaxScale(float scale, float[] values) {

if (scale * values[Matrix.MSCALE_X] > MAX_SCALE)

scale = MAX_SCALE / values[Matrix.MSCALE_X];

return scale;

}

private void reSetMatrix() {

if (checkRest()) {

mCurrentMatrix.set(mMatrix);

setImageMatrix(mCurrentMatrix);

} else {

float[] values = new float[9];

getImageMatrix().getValues(values);

float height = mImageHeight * values[Matrix.MSCALE_Y];

if (height < getHeight()) {

float topMargin = (getHeight() - height) / 2;

if (topMargin != values[Matrix.MTRANS_Y]) {

mCurrentMatrix.set(getImageMatrix());

mCurrentMatrix.postTranslate(0, topMargin

- values[Matrix.MTRANS_Y]);

setImageMatrix(mCurrentMatrix);

}

}

}

}

private boolean checkRest() {

float[] values = new float[9];

getImageMatrix().getValues(values);

float scale = values[Matrix.MSCALE_X];

return scale < mScale;

}

private void isMatrixEnable() {

if (getScaleType() != ScaleType.CENTER) {

setScaleType(ScaleType.MATRIX);

} else {

mMode = MODE_UNABLE;

}

}

private float distance(MotionEvent event) {

float dx = event.getX(1) - event.getX(0);

float dy = event.getY(1) - event.getY(0);

return (float) Math.sqrt(dx * dx + dy * dy);

}

public void onDoubleClick() {

float scale = isZoomChanged() ? 1 : DOUBLE_CLICK_SACLE;

mCurrentMatrix.set(mMatrix);

mCurrentMatrix.postScale(scale, scale, getWidth() / 2,

getHeight() / 2);

setImageMatrix(mCurrentMatrix);

}

}

private class GestureListener extends SimpleOnGestureListener {

private final MatrixTouchListener mTouchListener;

public GestureListener(MatrixTouchListener listener) {

this.mTouchListener = listener;

}

@Override

public boolean onDown(MotionEvent e) {

return true;

}

@Override

public boolean onDoubleTap(MotionEvent e) {

mTouchListener.onDoubleClick();

return true;

}

@Override

public boolean onSingleTapUp(MotionEvent e) {

return super.onSingleTapUp(e);

}

@Override

public void onLongPress(MotionEvent e) {

super.onLongPress(e);

}

@Override

public boolean onScroll(MotionEvent e1, MotionEvent e2,

float distanceX, float distanceY) {

return super.onScroll(e1, e2, distanceX, distanceY);

}

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {

return super.onFling(e1, e2, velocityX, velocityY);

}

@Override

public void onShowPress(MotionEvent e) {

super.onShowPress(e);

}

@Override

public boolean onDoubleTapEvent(MotionEvent e) {

return super.onDoubleTapEvent(e);

}

@Override

public boolean onSingleTapConfirmed(MotionEvent e) {

if (mSingleTapListener != null)

mSingleTapListener.onSingleTap(e);

return super.onSingleTapConfirmed(e);

}

}

public interface OnMovingListener {

public void startDrag();

public void stopDrag();

}

public interface OnSingleTapListener {

public void onSingleTap(MotionEvent e);

}

}

我对其中定义OnSingleTapListener接口的方法稍作了一些修改,为onSingleTap回调方法增加了MotionEvent类型的参数,来方便我们根据用户具体的事件内容作出对应的控制。

以上是 Android实现手势控制ImageView图片大小 的全部内容, 来源链接: utcz.com/z/314848.html

回到顶部