最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android實(shí)現(xiàn)手勢控制ImageView圖片大小

 更新時間:2016年02月15日 10:20:40   投稿:lijiao  
這篇文章主要介紹了Android實(shí)現(xiàn)手勢控制ImageView圖片大小的相關(guān)資料,需要的朋友可以參考下

本文實(shí)例實(shí)現(xiàn)的主要功能是在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回調(diào)方法增加了MotionEvent類型的參數(shù),來方便我們根據(jù)用戶具體的事件內(nèi)容作出對應(yīng)的控制。

以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)Android軟件編程有所幫助。

相關(guān)文章

  • Android Camera2采集攝像頭原始數(shù)據(jù)

    Android Camera2采集攝像頭原始數(shù)據(jù)

    這篇文章主要介紹了Android Camera2采集攝像頭原始數(shù)據(jù)并進(jìn)行手工預(yù)覽的功能實(shí)現(xiàn)原理以及代碼分析,需要的朋友學(xué)習(xí)下吧。
    2018-02-02
  • Android自定義view實(shí)現(xiàn)雪花特效實(shí)例代碼

    Android自定義view實(shí)現(xiàn)雪花特效實(shí)例代碼

    實(shí)現(xiàn)雪花的效果其實(shí)也可以通過自定義View的方式來實(shí)現(xiàn)的,而且操作上也相對簡單一些,下面這篇文章主要給大家介紹了關(guān)于Android自定義view實(shí)現(xiàn)雪花特效的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • Monkeyrunner 常用按鍵總結(jié)

    Monkeyrunner 常用按鍵總結(jié)

    這篇文章主要介紹了Monkeyrunner 常用按鍵總結(jié)的相關(guān)資料,這里對Monkeyrunner 按鍵的功能進(jìn)行詳細(xì)說明,需要的朋友可以參考下
    2016-11-11
  • Kotlin fun函數(shù)使用方法

    Kotlin fun函數(shù)使用方法

    函數(shù)是執(zhí)行特定任務(wù)的一組相互關(guān)聯(lián)的代碼塊。函數(shù)用于將程序分解為不同的子模塊。它使代碼可重用,并使程序更易于管理,這篇文章主要介紹了Kotlin fun函數(shù)使用方法
    2022-12-12
  • Android 滑動定位和吸附懸停效果實(shí)現(xiàn)代碼

    Android 滑動定位和吸附懸停效果實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android 滑動定位和吸附懸停效果實(shí)現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Android實(shí)現(xiàn)兩臺手機(jī)屏幕共享和遠(yuǎn)程控制功能

    Android實(shí)現(xiàn)兩臺手機(jī)屏幕共享和遠(yuǎn)程控制功能

    在遠(yuǎn)程協(xié)助、在線教學(xué)、技術(shù)支持等多種場景下,實(shí)時獲得另一部移動設(shè)備的屏幕畫面,并對其進(jìn)行操作,具有極高的應(yīng)用價值,本項(xiàng)目旨在實(shí)現(xiàn)兩臺 Android 手機(jī)之間的屏幕共享與遠(yuǎn)程控制,需要的朋友可以參考下
    2025-04-04
  • android recyclerview模擬聊天界面

    android recyclerview模擬聊天界面

    這篇文章主要為大家詳細(xì)介紹了android Listview模擬聊天界面的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 詳解Android中的ActivityThread和APP啟動過程

    詳解Android中的ActivityThread和APP啟動過程

    ActivityThread就是我們常說的主線程或UI線程,ActivityThread的main方法是整個APP的入口,本篇深入學(xué)習(xí)下ActivityThread,順便了解下APP和Activity的啟動過程。
    2021-06-06
  • Android 進(jìn)度條按鈕ProgressButton的實(shí)現(xiàn)代碼

    Android 進(jìn)度條按鈕ProgressButton的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android 進(jìn)度條按鈕實(shí)現(xiàn)(ProgressButton)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2018-10-10
  • Android Studio 3.0 Gradle 配置變更

    Android Studio 3.0 Gradle 配置變更

    這篇文章主要介紹了Android Studio 3.0 Gradle 配置變更的相關(guān)知識,即多渠道打包變更和更改打包命名及路徑的代碼,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-03-03

最新評論

松溪县| 万州区| 广安市| 安宁市| 汉寿县| 丽江市| 珠海市| 抚松县| 贡嘎县| 如东县| 京山县| 郴州市| 噶尔县| 南郑县| 新晃| 江阴市| 东阿县| 彩票| 康保县| 新绛县| 乌恰县| 大名县| 临邑县| 黑河市| 萨迦县| 桦川县| 朝阳区| 新平| 墨竹工卡县| 长白| 台北县| 武宣县| 利津县| 历史| 莱西市| 应用必备| 普定县| 江津市| 玛曲县| 日照市| 咸阳市|