效果图:
功能 :
可以随手指进行自由移动图片
按照适当的比例设置图片的显示
首先将图片按照适当的比例显示在自定义控件中(当图片的宽度或者高度大于控件的宽度或者高度的时候,会对图片进行适当的缩放,当图片的宽高小于控件的宽高的时候,可以进行适当比例的放大,当然后也可以设置是否要进行放大图片的操作,当图片的宽高小于控件的宽高的时候,设置图片显示在控件的中间位置)具体操作过程请点击下面第一条链接进行查看
适当比例设置显示图片:点击查看设置图片显示
设置可随手指自由缩放的图片:点击查看可自由缩放的ImageVeiw
设置双击放大或缩小的图片:点击查看可双击放大或缩小的ImageView
编写图片自由移动的过程分析
首先定义变量
/**
*记录上一次多点触控的数量
*/
private int mLastPointerCount;
/**
* 记录用户最后一次进行多点触控时的位置
*/
private float mLastX;
private float mLastY;
在onTouch方法中进行移动逻辑的操作
首先是获取当前的触控点的个数并计算出触摸中心点的位置
当 当前的触控点的个数发生变化时,记录当前触摸的中心点的位置
//用于存储多点触控的中心点
float x = 0;
float y = 0;
//获取多点触控的数量
final int pointerCount = event.getPointerCount();
for (int i = 0; i < pointerCount; i++) {
x+=event.getX(i);
y+=event.getY(i);
}
//获取中心点的位置
x/=pointerCount;
y/=pointerCount;
//说明手指数量发生变化,重新记录中心点坐标
if(mLastPointerCount!=pointerCount){
mLastX = x;
mLastY = y;
}
//记录多点触控的数量
mLastPointerCount = pointerCount;
然后定义方法 获取当前的图片的宽度与高度,并在onTouch方法 中调用获取到保存信息的ReceF
private RectF getMatrixRectF() {
Matrix matrix = mMatrix;
final RectF rectF = new RectF();
final Drawable drawable = getDrawable();
if (drawable != null) {
rectF.set(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
matrix.mapRect(rectF);
}
return rectF;
}
在onTouch方法中进行调用
final RectF matrixRectF1 = getMatrixRectF();
这里的matrixRectF1就是保存了图片位置及大小信息的对象,这里获取的目的是为了对移动图片的过程中进行一些限制,比如,当图片的宽度高度小于控件的宽与高,就不能进行移动,或者是说当图片的宽高小于控件的宽高,进行自由移动,当手指抬起的进修,将图片自动设置显示在控件中央等等,这完全看个人的需求,如果涉及到这样类似的限制,那么就需要matrixRectF1这个包含图片所有信息的对象来调用了
处理手指的按下移动抬起事件并设置图片随着手指的移动而移动(onTouch方法中)
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
处理ACTION_DOWN中的操作,在这里,我们可以进行一步操作,就是判断一个当前的图片,如果当前的图片的宽度或者高度大于控件的宽度与高度,那么我们可以设置
图片随手指的移动处理逻辑主要是在ACTION_MOVE事件中
case MotionEvent.ACTION_MOVE:
//计算偏移量
float dx = x - mLastX;
float dy = y - mLastY;
//判断当前是否在移动
if (!mIsCanDrag){
mIsCanDrag = isMovesAction(dx, dy);
}
if (mIsCanDrag) {
//如果可以进行移动
isCheckLeftAndRight = isCheckTopAndBottom = true;
//拿到缩放后的图片的宽高
final RectF matrixRectF = getMatrixRectF();
if (getDrawable()!=null){
// //如果图片宽度小于控件宽度,不可以进行横向移动
// if (matrixRectF.width()<getWidth()){
// isCheckLeftAndRight = false;
// dx =0;
// }
// //如果图片高度小于控件的高度,不可以进行纵向移动
// if (matrixRectF.height()<getHeight()){
// isCheckTopAndBottom = false;
// dy =0;
// }
mMatrix.postTranslate(dx, dy);
setImageMatrix(mMatrix);
}
}
//移动过程中时刻记录更新移动的坐标
mLastX = x;
mLastY = y;
break;
可以看的到,在这里,我们有一个方法是判断当前是否可进行移动
private boolean isMovesAction(float dx, float dy) {
return Math.sqrt(dx*dx+dy*dy)>mTouchSlop;
}
这里使用到一个mTouchSlop变量,我们需要在构造方法中进行初始化操作
private int mTouchSlop;
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件
最后,我们需要在ACTION_UP事件中更新mLastPointerCount
case MotionEvent.ACTION_CANCEL:
mLastPointerCount = 0;
到这里,我们就实现了图片可以随手指进行多指触控实现自由移动了;
处理多指触控自由移动图片与ViewPager的滑动冲突问题
在这里,我们可以进行判定,当图片的宽度高度大于当前的宽度与高度的时候,可以自由移动图片,ViewPager不可以左右滑动,当图片的宽高小于控件的宽高的时候,不允许移动图片,可以滑动viewPager
我们可以在ACTION_MOVE: ACTION_DOWN方法中判断并处理相关事件
case MotionEvent.ACTION_DOWN:
//当前的图片是放大的状态的时候,屏蔽父控件的鎆触摸事件
if (matrixRectF1.width()>getWidth()+0.01||matrixRectF1.height()>getHeight()+0.01){
getParent().requestDisallowInterceptTouchEvent(true);
}
}
break;
case MotionEvent.ACTION_MOVE:
if (matrixRectF1.width()>getWidth()+0.01||matrixRectF1.height()>getHeight()+0.01){
getParent().requestDisallowInterceptTouchEvent(true);
}
处理当图片的宽高小于控件的宽高时候,手指抬起时候将图片移动到控件中心显示
在这里,可以在ACTION_UP事件触发时候进行处理
case MotionEvent.ACTION_CANCEL:
//当我们的图片的宽度与高度小于控件的宽度与高度的时候,最后手指抬起的时候我们将其移动到控件中心
final RectF matrixRectF = getMatrixRectF();
float deltaX=1.0f;
float deltaY=1.0f;
if (matrixRectF.width() < getWidth()||matrixRectF.height() < getHeight()) {
if (matrixRectF.width() < getWidth()) {
deltaX = getWidth() / 2 - matrixRectF.right + matrixRectF.width() / 2;
}
if (matrixRectF.height() < getHeight()) {
deltaY = getHeight() / 2 - matrixRectF.bottom + matrixRectF.height() / 2;
}
mMatrix.postTranslate(deltaX, deltaY);
setImageMatrix(mMatrix);
}
break
具体的移动操作距离,可参考上一博文的分析 点击查看移动距离计算分析
效果图:
处理当图片的宽高小于控件的宽高时候,手指抬起时候将图片缓慢移动到控件中心显示
本篇脑筋急转弯解析: 稀饭, 因为物以稀为贵