栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

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

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 onSingleTap/confirm/ied(MotionEvent e) {
      if (mSingleTapListener != null)
 mSingleTapListener.onSingleTap(e);
      return super.onSingleTap/confirm/ied(e);
    }
  }
  public interface onMovingListener {
    public void startDrag();

    public void stopDrag();
  }
  public interface onSingleTapListener {
    public void onSingleTap(MotionEvent e);
  }
}

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

以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/163260.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号