author:andy
问题:产品要求,做成双指缩放且双指拖拽
android市面上应用最常见的一个功能是双指缩放,然后单指拖拽。比如最著名的PhotoView开源,就是典型代表。然而Google了半天基本找不到双指缩放和双指拖拽的完整资料,而且网上也有一些用户提出相同的问题,然而并没有好的开源,就自己整了个。
先上图:
思路流程图:
注意的事项:
MotionEvent:对应的几个关键事件
MotionEvent.ACTION_POINTER_DOWN: 第二根以上手指触摸屏幕触发:
在第二个手指的监听记录初始位置,记录2个手指开始的间距oldDist:
case MotionEvent.ACTION_POINTER_DOWN:
if (pointerCount == 2) {
downX1 = event.getX(0);
downX2 = event.getX(1);
downY1 = event.getY(0);
downY2 = event.getY(1);
Log.d(TAG, "ACTION_POINTER_DOWN 双指按下 downX1=" + downX1 + " downX2="
+ downX2 + " downY1=" + downY1 + " downY2=" + downY2);
oldDist = spacing(event); //两点按下时的距离
}
手指移动过程缩放和移动处理:
oldDist:2手指初始距离
moveDist: 2手指移动后的距离
space: 2手指变化距离
缩放比例:float scale = (float) (getScaleX() + space / v.getWidth());
移动处理:以2指中心点变化值作为移动范围
case MotionEvent.ACTION_MOVE:
if (pointerCount == 2) {
float x1 = event.getX(0);
float x2 = event.getX(1);
float y1 = event.getY(0);
float y2 = event.getY(1);
double changeX1 = x1 - downX1;
double changeX2 = x2 - downX2;
double changeY1 = y1 - downY1;
double changeY2 = y2 - downY2;
if (getScaleX() > 1) { //滑动
float lessX = (float) ((changeX1) / 2 + (changeX2) / 2);
float lessY = (float) ((changeY1) / 2 + (changeY2) / 2);
setSelfPivot(-lessX, -lessY);
Log.d(TAG, "此时为滑动");
}
//缩放处理
moveDist = spacing(event);
double space = moveDist - oldDist;
float scale = (float) (getScaleX() + space / v.getWidth());
if (scale < SCALE_MIN) {
setScale(SCALE_MIN);
} else if (scale > SCALE_MAX) {
setScale(SCALE_MAX);
} else {
setScale(scale);
}
}
break;
间距计算
/**
* 计算两个点的距离
*
* @param event
* @return
*/
private double spacing(MotionEvent event) {
if (event.getPointerCount() == 2) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return Math.sqrt(x * x + y * y);
} else {
return 0;
}
}
平移
/**
* 平移画面,当画面的宽或高大于屏幕宽高时,调用此方法进行平移
*
* @param x
* @param y
*/
public void setPivot(float x, float y) {
setPivotX(x);
setPivotY(y);
}v
平移加上屏幕边界处理
/**
* 移动
*
* @param lessX
* @param lessY
*/
private void setSelfPivot(float lessX, float lessY) {
float setPivotX = 0;
float setPivotY = 0;
setPivotX = getPivotX() + lessX;
setPivotY = getPivotY() + lessY;
if (setPivotX < 0 && setPivotY < 0) {
setPivotX = 0;
setPivotY = 0;
} else if (setPivotX > 0 && setPivotY < 0) {
setPivotY = 0;
if (setPivotX > getWidth()) {
setPivotX = getWidth();
}
} else if (setPivotX < 0 && setPivotY > 0) {
setPivotX = 0;
if (setPivotY > getHeight()) {
setPivotY = getHeight();
}
} else {
if (setPivotX > getWidth()) {
setPivotX = getWidth();
}
if (setPivotY > getHeight()) {
setPivotY = getHeight();
}
}
setPivot(setPivotX, setPivotY);
}
碰到的问题:
最初构思的时候,走进了个误区,以为缩放和拖拽必须二选一,于是出现很多的计算判断用户到底是缩放还是拖拽,然后相应处理,然而无论怎么计算,发现都有瑕疵(体现在:滑动时候出现缩放,缩放时有时候又夹杂滑动,导致感觉不流畅),最后发现其实根本无需如此,二者完全可以共存,而且体验完全流畅.