阅读 212

Android自定义View相册图片的放大缩小

ScaleGestureDetector这个类是专门用来检测两个手指在屏幕上做缩放的手势用的 根据接收的 MotionEven,侦测由多个触点(多点触控)引发的变形手势。callback 方法ScaleGestureDetector.OnScaleGestureListener会在特定手势事件发生时通知用户。该类仅能和Touch事件引发的 MotionEvent 配合使用。

使用该类需要为View创建ScaleGestureDetector实例 确保在 onTouchEvent(MotionEvent)方法中调用onTouchEvent (MotionEvent)。在事件发生时,定义在 callback中的方法会被调用。 (ScaleGestureDetector 为 Android2.2 新增的类,允许 Views 可以通过提供的MotionEvents 检测和处理包括多点触摸在内的手势变化信息。

public ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener) 复制代码

       构造函数\

ScaleGestureDetector公共方法

public float getCurrentSpan ()

返回手势过程中,组成该手势的两个触点的当前距离。 返回值 以像素为单位的触点距离。

public long getEventTime ()

返回事件被捕捉时的时间。 返回值 以毫秒为单位的事件时间。

public float getFocusX ()

返回当前手势焦点的 X 坐标。 如果手势正在进行中,焦点位于组成手势的两个触点之间。
手势正在结束,焦点为仍留在屏幕上的触点的位置。
isInProgress()返回 false,该方法的返回值未定义。返回值返回焦点的 X 坐标值,以像素为单位。

public float getFocusY ()

       返回当前手势焦点的 Y 坐标。 如果手势正在进行中,焦点位于组成手势的两个触点之间。 如果手势正在结束,焦点为仍留在屏幕上的触点的位置。若 isInProgress()返回 false,该方法的返回值未定义。
返回值
返回焦点的 Y 坐标值,以像素为单位。

pblic float getPreviousSpan ()


返回手势过程中,组成该手势的两个触点的前一次距离。
返回值
两点的前一次距离,以像素为单位。

public float getScaleFactor ()


返回从前一个伸缩事件至当前伸缩事件的伸缩比率。该值定义为  (getCurrentSpan()  / getPreviousSpan())。
返回值
当前伸缩比率.

pblic long getTimeDelta ()


返回前一次接收到的伸缩事件距当前伸缩事件的时间差,以毫秒为单位。
返回值
从前一次伸缩事件起始的时间差,以毫秒为单位。\

public boolean isInProgress ()

如果手势处于进行过程中,返回 true.
返回值
如果手势处于进行过程中,返回 true。否则返回 false。

部分内容引用Android ScaleGestureDetector - - ITeye博客

重写ImageView

public class TouchImageView extends ImageView  复制代码

触摸滑动后有三种状态\

初始 拖动 放大

完整代码 代码里面有注释

public class TouchImageView extends ImageView {     Matrix matrix;     // We can be in one of these 3 states     static final int NONE = 0;  //初始     static final int DRAG = 1;  //拖动     static final int ZOOM = 2;  //放大     int mode = NONE;     // 记住一些关于缩放的     PointF last = new PointF();     PointF start = new PointF();     float minScale = 1f;     float maxScale = 3f;     float[] m;     int viewWidth, viewHeight;     static final int CLICK = 3;     float saveScale = 1f;     protected float origWidth, origHeight;     int oldMeasuredWidth, oldMeasuredHeight;     //缩放手势检测     ScaleGestureDetector mScaleDetector;     Context context;     //默认构造函数     public TouchImageView(Context context) {         super(context);         sharedConstructing(context);     }     public TouchImageView(Context context, AttributeSet attrs) {         super(context, attrs);         sharedConstructing(context);     }     private void sharedConstructing(Context context) {         super.setClickable(true);         this.context = context;         mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());         matrix = new Matrix();         m = new float[9];         setImageMatrix(matrix);         setScaleType(ScaleType.MATRIX);         setOnTouchListener(new OnTouchListener() {             @Override             public boolean onTouch(View v, MotionEvent event) {                 mScaleDetector.onTouchEvent(event);                 PointF curr = new PointF(event.getX(), event.getY());                 switch (event.getAction()) {                     case MotionEvent.ACTION_DOWN:                         last.set(curr);  //当前位置                         start.set(last);  //开始点                         mode = DRAG;                         break;                     case MotionEvent.ACTION_MOVE:    //移动事件                         if (mode == DRAG) {                             float deltaX = curr.x - last.x;                             float deltaY = curr.y - last.y;                             //拖拽位置                             float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);                             float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);                             matrix.postTranslate(fixTransX, fixTransY);                             fixTrans();                             last.set(curr.x, curr.y);                         }                         break;                     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;                     //有手指离开屏幕,但屏幕还有触点(手指)                     case MotionEvent.ACTION_POINTER_UP:                         mode = NONE;                         break;                 }                 setImageMatrix(matrix);                 invalidate();                 return true; // 指示事件已处理             }         });     }     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;             }             if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)                 matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);             else                 matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());             fixTrans();             return true;         }     }     void fixTrans() {         matrix.getValues(m);         float transX = m[Matrix.MTRANS_X];         float transY = m[Matrix.MTRANS_Y];         float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);         float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);         if (fixTransX != 0 || fixTransY != 0)             matrix.postTranslate(fixTransX, fixTransY);     }     float getFixTrans(float trans, float viewSize, float contentSize) {         float minTrans, maxTrans;         if (contentSize <= viewSize) {             minTrans = 0;             maxTrans = viewSize - contentSize;         } else {             minTrans = viewSize - contentSize;             maxTrans = 0;         }         if (trans < minTrans)             return -trans + minTrans;         if (trans > maxTrans)             return -trans + maxTrans;         return 0;     }     float getFixDragTrans(float delta, float viewSize, float contentSize) {         if (contentSize <= viewSize) {             return 0;         }         return delta;     }     @Override     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         viewWidth = MeasureSpec.getSize(widthMeasureSpec);         viewHeight = MeasureSpec.getSize(heightMeasureSpec);         //         // 旋转时重新缩放图像         //         if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight                 || viewWidth == 0 || viewHeight == 0)             return;         oldMeasuredHeight = viewHeight;         oldMeasuredWidth = viewWidth;         if (saveScale == 1) {             //Fit to screen.             float scale;            //获取图片             Drawable drawable = getDrawable();             if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)                 return;             int bmWidth = drawable.getIntrinsicWidth();             int bmHeight = drawable.getIntrinsicHeight();             Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);             float scaleX = (float) viewWidth / (float) bmWidth;             float scaleY = (float) viewHeight / (float) bmHeight;             scale = Math.min(scaleX, scaleY);             matrix.setScale(scale, scale);             // 将图像居中             float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);             float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);             redundantYSpace /= (float) 2;             redundantXSpace /= (float) 2;             matrix.postTranslate(redundantXSpace, redundantYSpace);             origWidth = viewWidth - 2 * redundantXSpace;             origHeight = viewHeight - 2 * redundantYSpace;             setImageMatrix(matrix);         }         fixTrans();     }     // 用于标记滑动的坐标     private int downX= 0;     private int downY= 0;     @Override     public boolean dispatchTouchEvent(MotionEvent ev) {         int x = (int) ev.getX();         int y = (int) ev.getY();         switch (ev.getAction()) {             case MotionEvent.ACTION_DOWN: {                 getParent().requestDisallowInterceptTouchEvent(false);                 break;             }             case MotionEvent.ACTION_MOVE: {                 int deltaX = x - downX;                 int deltaY = y - downX;                 //左右滑动                 if (Math.abs(deltaX) > Math.abs(deltaY)*50                 ) {                 //拦截事件分发                     getParent().requestDisallowInterceptTouchEvent(true);                 }                 break;             }             case MotionEvent.ACTION_UP: {                 getParent().requestDisallowInterceptTouchEvent(false);                 break;             }         }         //赋值         downX= x;         downX= y;         return super.dispatchTouchEvent(ev);     } } 复制代码

调用方法

TouchImageView mImg; mImg =itemView.findViewById(R.id.MyZoomImageView); mImg.setMaxZoom(4f); mImg.setImageBitmap(bit); 复制代码

效果图:

ezgif.com-gif-maker (4).gif


作者:九狼
链接:https://juejin.cn/post/7034165761438384142

 伪原创工具 https://www.237it.com/ 


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐