本文实例实现的主要功能是在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;}@Overridepublic 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();@Overridepublic 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;}@Overridepublic boolean onDown(MotionEvent e) {return true;}@Overridepublic boolean onDoubleTap(MotionEvent e) {mTouchListener.onDoubleClick();return true;}@Overridepublic boolean onSingleTapUp(MotionEvent e) {return super.onSingleTapUp(e);}@Overridepublic void onLongPress(MotionEvent e) {super.onLongPress(e);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {return super.onFling(e1, e2, velocityX, velocityY);}@Overridepublic void onShowPress(MotionEvent e) {super.onShowPress(e);}@Overridepublic boolean onDoubleTapEvent(MotionEvent e) {return super.onDoubleTapEvent(e);}@Overridepublic 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软件编程有所帮助。