Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

转载请标明出处:,本文出自:【张鸿洋的博客】

上一篇已经带大家实现了自由的放大缩小图片,简单介绍了下Matrix;具体请参考:Android 手势检测实战 打造支持缩放平移的图片预览效果(上);本篇继续完善我们的ImageView~~

首先加入放大后的移动~~

1、自由的进行移动

我们在onTouchEvent里面,加上移动的代码,当然了,必须长或宽大于屏幕才可以移动~~~

@Overridepublic boolean onTouch(View v, MotionEvent event){mScaleGestureDetector.onTouchEvent(event);float x = 0, y = 0;// 拿到触摸点的个数final int pointerCount = event.getPointerCount();// 得到多个触摸点的x与y均值for (int i = 0; i < pointerCount; i++){x += event.getX(i);y += event.getY(i);}x = x / pointerCount;y = y / pointerCount;/** * 每当触摸点发生变化时,重置mLasX , mLastY*/if (pointerCount != lastPointerCount){isCanDrag = false;mLastX = x;mLastY = y;}lastPointerCount = pointerCount;switch (event.getAction()){case MotionEvent.ACTION_MOVE:Log.e(TAG, "ACTION_MOVE");float dx = x – mLastX;float dy = y – mLastY;if (!isCanDrag){isCanDrag = isCanDrag(dx, dy);}if (isCanDrag){RectF rectF = getMatrixRectF();if (getDrawable() != null){isCheckLeftAndRight = isCheckTopAndBottom = true;// 如果宽度小于屏幕宽度,则禁止左右移动if (rectF.width() < getWidth()){dx = 0;isCheckLeftAndRight = false;}// 如果高度小雨屏幕高度,则禁止上下移动if (rectF.height() < getHeight()){dy = 0;isCheckTopAndBottom = false;}mScaleMatrix.postTranslate(dx, dy);checkMatrixBounds();setImageMatrix(mScaleMatrix);}}mLastX = x;mLastY = y;break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:Log.e(TAG, "ACTION_UP");lastPointerCount = 0;break;}return true;}首先我们拿到触摸点的数量,然后求出多个触摸点的平均值,设置给我们的mLastX , mLastY , 然后在移动的时候,得到dx ,dy 进行范围检查以后,调用mScaleMatrix.postTranslate进行设置偏移量,当然了,设置完成以后,还需要再次校验一下,不能把图片移动的与屏幕边界出现白边,校验完成后,调用setImageMatrix.

这里:需要注意一下,我们没有复写ACTION_DOWM,是因为,ACTION_DOWN在多点触控的情况下,只要有一个手指按下状态,其他手指按下不会再次触发ACTION_DOWN,但是多个手指以后,触摸点的平均值会发生很大变化,所以我们没有用到ACTION_DOWN。每当触摸点的数量变化,我们就会跟新当前的mLastX,mLastY.

下面是上面用到的两个私有方法,一个用于检查边界,一个用于判断是否是拖动的操作:

/** * 移动时,进行边界判断,主要判断宽或高大于屏幕的 */private void checkMatrixBounds(){RectF rect = getMatrixRectF();float deltaX = 0, deltaY = 0;final float viewWidth = getWidth();final float viewHeight = getHeight();// 判断移动或缩放后,图片显示是否超出屏幕边界if (rect.top > 0 && isCheckTopAndBottom){deltaY = -rect.top;}if (rect.bottom < viewHeight && isCheckTopAndBottom){deltaY = viewHeight – rect.bottom;}if (rect.left > 0 && isCheckLeftAndRight){deltaX = -rect.left;}if (rect.right < viewWidth && isCheckLeftAndRight){deltaX = viewWidth – rect.right;}mScaleMatrix.postTranslate(deltaX, deltaY);}/** * 是否是推动行为 * * @param dx * @param dy * @return */private boolean isCanDrag(float dx, float dy){return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;}这样,我们就可以快乐的放大、缩小加移动了~~~

效果图:这次换个男人的图片,我们越狱的主角之一,TBug~

我们的缩放+移动搞定~~

2、双击放大与缩小

谈到双击事件,我们的GestureDetector终于要登场了,这哥们可以捕获双击事件~~

1、GestureDetector的使用

因为GestureDetector设置监听器的话,方法一大串,而我们只需要onDoubleTap这个回调,所以我们准备使用它的一个内部类SimpleOnGestureListener,对接口的其他方法实现了空实现。

不过还有几个问题需要讨论下,才能开始我们的代码:

1、我们双击尺寸如何变化?

我是这样的,根据当前的缩放值,如果是小于2的,我们双击直接到变为原图的2倍;如果是2,4之间的,我们双击直接为原图的4倍;其他状态也就是4倍,双击后还原到最初的尺寸。

如果你觉得这样不合适,可以根据自己的爱好调整。

2、我们双击变化,需要一个动画~~比如我们上例的演示图,图片很大,全屏显示的时候initScale=0.5左后,如果双击后变为2,也就是瞬间大了四倍,没有一个过渡的效果的话,给用户的感觉会特别差。所以,我们准备使用postDelay执行一个Runnable,Runnable中再次根据的当然的缩放值继续执行。

首先我们在构造方法中,完成对GestureDetector的初始化,以及设置onDoubleTap监听

public ZoomImageView(Context context, AttributeSet attrs){super(context, attrs);mScaleGestureDetector = new ScaleGestureDetector(context, this);mGestureDetector = new GestureDetector(context,new SimpleOnGestureListener(){@Overridepublic boolean onDoubleTap(MotionEvent e){if (isAutoScale == true)return true;float x = e.getX();float y = e.getY();Log.e("DoubleTap", getScale() + " , " + initScale);if (getScale() < SCALE_MID){ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MID, x, y), 16);isAutoScale = true;} else if (getScale() >= SCALE_MID&& getScale() < SCALE_MAX){ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MAX, x, y), 16);isAutoScale = true;} else{ZoomImageView.this.postDelayed(new AutoScaleRunnable(initScale, x, y), 16);isAutoScale = true;}return true;}});mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();super.setScaleType(ScaleType.MATRIX);this.setOnTouchListener(this);}

1、当双击的时候,首先判断是否正在自动缩放,如果在,直接retrun ;

2、然后就进入了我们的if,如果当然是scale小于2,则通过view.发送一个Runnable进行执行;其他类似;

痛苦留给的一切,请细加回味!苦难一经过去,苦难就变为甘美。

Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

相关文章:

你感兴趣的文章:

标签云: