我是Android开发的新手,正在尝试掌握多点触控输入。我开始使用一个简单的应用程序,允许用户通过拖动和释放一个手指在画布上创建矩形,这一部分已经实现了。为了扩展功能,我想让用户能够使用第二个手指旋转他们正在绘制的矩形,这时我的问题开始了。目前的情况是,添加第二个手指会导致多个矩形旋转,而不仅仅是当前的矩形。但是它们将在第二个手指释放时恢复到默认方向。
我已经花了一段时间来研究它,我认为我的核心问题是我对来自两个(或更多)手指的多个MotionEvents处理不当。我留下的显示每个事件在屏幕上坐标的日志语句仍然与触摸屏幕的第一个手指绑定,而不是切换到第二个手指。我已经尝试了多种访问和更改事件指针ID的配置,但仍然没有运气。如果有人能提供一些指导意见,我将非常感激。
我的代码如下:
我已经花了一段时间来研究它,我认为我的核心问题是我对来自两个(或更多)手指的多个MotionEvents处理不当。我留下的显示每个事件在屏幕上坐标的日志语句仍然与触摸屏幕的第一个手指绑定,而不是切换到第二个手指。我已经尝试了多种访问和更改事件指针ID的配置,但仍然没有运气。如果有人能提供一些指导意见,我将非常感激。
我的代码如下:
public class BoxDrawingView extends View {
private static final String TAG = "BoxDrawingView";
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private Box mCurrentBox;
private List<Box> mBoxen = new ArrayList<>();
private Float mLastTouchX;
private Float mLastTouchY;
...
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(MotionEventCompat.getActionMasked(event)) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(event, 0);
current = new PointF(MotionEventCompat.getX(event, mActivePointerId),
MotionEventCompat.getY(event, mActivePointerId));
action = "ACTION_DOWN";
// Reset drawing state
mCurrentBox = new Box(current);
mBoxen.add(mCurrentBox);
mLastTouchX = MotionEventCompat.getX(event, MotionEventCompat.getPointerId(event, 0));
mLastTouchY = MotionEventCompat.getY(event, MotionEventCompat.getPointerId(event, 0));
break;
case MotionEvent.ACTION_POINTER_DOWN:
action = "ACTION_POINTER_DOWN";
mActivePointerId = MotionEventCompat.getPointerId(event, 0);
mLastTouchX = MotionEventCompat.getX(event, MotionEventCompat.getPointerId(event, 0));
mLastTouchY = MotionEventCompat.getY(event, MotionEventCompat.getPointerId(event, 0));
break;
case MotionEvent.ACTION_MOVE:
action = "ACTION_MOVE";
current = new PointF(MotionEventCompat.getX(event, mActivePointerId),
MotionEventCompat.getY(event, mActivePointerId));
if (mCurrentBox != null) {
mCurrentBox.setCurrent(current);
invalidate();
}
if(MotionEventCompat.getPointerCount(event) > 1) {
int pointerIndex = MotionEventCompat.findPointerIndex(event, mActivePointerId);
float currX = MotionEventCompat.getX(event, pointerIndex);
float currY = MotionEventCompat.getY(event, pointerIndex);
if(mLastTouchX < currX) {
// simplified: only use x coordinates for rotation for now.
// +X for clockwise, -X for counter clockwise
Log.d(TAG, "Clockwise");
mRotationAngle = 30;
}
else if (mLastTouchX > getX()) {
Log.d(TAG, "Counter clockwise");
mRotationAngle = -30;
}
}
break;
case MotionEvent.ACTION_UP:
action = "ACTION_UP";
mCurrentBox = null;
mLastTouchX = null;
mLastTouchY = null;
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
action = "ACTION_POINTER_UP";
int pointerIndex = event.getActionIndex();
int pointerId = event.getPointerId(pointerIndex);
if(pointerId == mActivePointerId){
mActivePointerId = INVALID_POINTER_ID;
}
break;
case MotionEvent.ACTION_CANCEL:
action = "ACTION_CANCEL";
mCurrentBox = null;
mActivePointerId = INVALID_POINTER_ID;
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas){
// Fill the background
canvas.drawPaint(mBackgroundPaint);
for(Box box : mBoxen) {
// Box is a custom object. Origin is the origin point,
// Current is the point of the opposite diagonal corner
float left = Math.min(box.getOrigin().x, box.getCurrent().x);
float right = Math.max(box.getOrigin().x, box.getCurrent().x);
float top = Math.min(box.getOrigin().y, box.getCurrent().y);
float bottom = Math.max(box.getOrigin().y, box.getCurrent().y);
if(mRotationAngle != 0) {
canvas.save();
canvas.rotate(mRotationAngle);
canvas.drawRect(left, top, right, bottom, mBoxPaint);
canvas.rotate(-mRotationAngle);
canvas.restore();
mRotationAngle = 0;
} else {
canvas.drawRect(left, top, right, bottom, mBoxPaint);
}
}
}
}