欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  技术分享

Android手势识别例子_图片缩放平移预览效果Demo

程序员文章站 2022-03-01 15:00:50
...

Android 手势实例、例子主要实现了图片的放大和缩小功能、以及双击放大与缩小

首先我们拿到触摸点的数量、然后求出多个触摸点的平均值、设置给我们的mLastX、mLastY

然后在移动的时候、得到dx、dy进行范围检查以后、调用mScaleMatrix.postTranslate进行设置偏移量

当然了、设置完成以后、还需要再次校验一下、不能把图片移动的与屏幕边界出现白边、校验完成后、调用setImageMatrix.

这里:需要注意一下、我们没有复写ACTION_DOWM、是因为、ACTION_DOWN在多点触控的情况下

只要有一个手指按下状态、其他手指按下不会再次触发ACTION_DOWN、但是多个手指以后、触摸点的平均值会发生很大变化

所以我们没有用到ACTION_DOWN、每当触摸点的数量变化、我们就会跟新当前的mLastX,mLastY.

public boolean onTouch(View v, MotionEvent event)
{
	if (mGestureDetector.onTouchEvent(event))
		return true;
	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;
	RectF rectF = getMatrixRectF();
	switch (event.getAction())
	{
	case MotionEvent.ACTION_DOWN:
		if (rectF.width() > getWidth() || rectF.height() > getHeight())
		{
			getParent().requestDisallowInterceptTouchEvent(true);
		}
		break;
	case MotionEvent.ACTION_MOVE:
		if (rectF.width() > getWidth() || rectF.height() > getHeight())
		{
			getParent().requestDisallowInterceptTouchEvent(true);
		}
		Log.e(TAG, "ACTION_MOVE");
		float dx = x - mLastX;
		float dy = y - mLastY;

		if (!isCanDrag)
		{
			isCanDrag = isCanDrag(dx, dy);
		}
		if (isCanDrag)
		{
			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;
}


双击放大与缩小、我们使用了GestureDetector、可以捕获双击事件

因为GestureDetector设置监听器的话、方法一大串、而我们只需要onDoubleTap这个回调

所以我们准备使用它的一个内部类SimpleOnGestureListener、对接口的其他方法实现了空实现

那么、我们双击尺寸如何变化?我是这样的、根据当前的缩放值、如果是小于2的、我们双击直接到变为原图的2倍

如果是2,4之间的、我们双击直接为原图的4倍;其他状态也就是4倍、双击后还原到最初的尺寸

我们双击变化、需要一个动画、比如我们上例的演示图、图片很大、全屏显示的时候initScale=0.5左后

如果双击后变为2、也就是瞬间大了四倍、没有一个过渡的效果的话、给用户的感觉会特别差

所以、我们准备使用postDelay执行一个Runnable、Runnable中再次根据的当然的缩放值继续执行

private class AutoScaleRunnable implements Runnable
{
	static final float BIGGER = 1.07f;
	static final float SMALLER = 0.93f;
	private float mTargetScale;
	private float tmpScale;

	//缩放的中心
	private float x;
	private float y;

	//传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小
	public AutoScaleRunnable(float targetScale, float x, float y)
	{
		this.mTargetScale = targetScale;
		this.x = x;
		this.y = y;
		if (getScale() < mTargetScale)
		{
			tmpScale = BIGGER;
		} else
		{
			tmpScale = SMALLER;
		}
	}

	@Override
	public void run()
	{
		// 进行缩放
		mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
		checkBorderAndCenterWhenScale();
		setImageMatrix(mScaleMatrix);

		final float currentScale = getScale();
		// 如果值在合法范围内,继续缩放
		if (((tmpScale > 1f) && (currentScale < mTargetScale))
				|| ((tmpScale < 1f) && (mTargetScale < currentScale)))
		{
			ZoomImageView.this.postDelayed(this, 16);
		} else
		// 设置为目标的缩放比例
		{
			final float deltaScale = mTargetScale / currentScale;
			mScaleMatrix.postScale(deltaScale, deltaScale, x, y);
			checkBorderAndCenterWhenScale();
			setImageMatrix(mScaleMatrix);
			isAutoScale = false;
		}
	}
}


代码就贴到这里、源代码下载链接: http://dwtedx.com/download.html?bdkey=s/1ntwVtDf 密码: lpya