MotionEvent中getAction( )与getActionMasked( )的区别:
getAction( )得到的值是由触控点index + 触控事件 构成;
getActionMasked( )得到的值仅由 触控事件 构成.
onTouchEvent(MotionEvent event)的实现:
public boolean onTouchEvent(MotionEvent event){
PointF current=new PointF(event.getX(),event.getY());
String action="";
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:
action="ACTION_DOWN";
mCurrentBox=new Box(current);
mBoxen.add(mCurrentBox);
pointer1=event.getPointerId(event.getActionIndex()); //当第一个手指触摸到屏幕后,记录第一个触控点的ID
break;
case MotionEvent.ACTION_POINTER_DOWN:
action="ACTION_POINTER_DOWN";
pointer2=event.getPointerId(event.getActionIndex()); //当第二个手指触摸到屏幕后,记录第二个触控点的ID
fx=event.getX(event.findPointerIndex(pointer1));
fy=event.getY(event.findPointerIndex(pointer1));
sx=event.getX(event.findPointerIndex(pointer2));
sy=event.getY(event.findPointerIndex(pointer2)); //得到第一,第二个触控点的横,纵坐标
mCurrentBox=null;
break;
case MotionEvent.ACTION_UP:
action="ACTION_UP";
pointer1=-1;
mCurrentBox=null;
break;
case MotionEvent.ACTION_POINTER_UP:
action="ACTION_POINTER_UP";
pointer2=-1;
break;
case MotionEvent.ACTION_MOVE:
action="ACTION_MOVE";
if(pointer1!=removed && pointer2!=removed){
nfx=event.getX(event.findPointerIndex(pointer1));
nfy=event.getY(event.findPointerIndex(pointer1));
nsx=event.getX(event.findPointerIndex(pointer2));
nsy=event.getY(event.findPointerIndex(pointer2)); //得到手指移动后第一,第二个触控点的横,纵坐标
mAngle=angleBetweenLines(fx,fy,sx,sy,nfx,nfy,nsx,nsy); //计算移动前后的角度差值
}
if(mCurrentBox!=null && pointer2==removed){
mCurrentBox.setCurrent(current);
}
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
action="ACTION_CANCEL";
mCurrentBox=null;
pointer1=-1;
pointer2=-1;
break;
default:;
}
Log.d(TAG,"action "+action+" at x="+current.x+" y="+current.y);
return true;
}
其中注意ACTION_DOWN与ACTION_POINTER_DOWN的区别,ACTION_DOWN是在第一根手指触摸屏幕时产生的事件,而ACTION_POINTER_DOWN是在多点触控下(也就是已经有手指触摸在屏幕上),又有一根手指触摸屏幕产生的事件。
上面代码中angleBetweenLines( )方法的实现:
public float angleBetweenLines(float fx, float fy, float sx, float sy, float nfx, float nfy, float nsx, float nsy){
float radian1=(float)Math.atan2(fy-sy,fx-sx);
float radian2=(float)Math.atan2(nfy-nsy,nfx-nsx);
float angle=(float)(Math.toDegrees(radian2-radian1)%360);
if(angle<0){
angle+=360;
}
return angle;
}
利用反三角函数atan2( )计算出对应斜率的弧度,移动前后的弧度值相减,并转换为角度值。
onDraw( Canvas)的实现:
public void onDraw(Canvas canvas){
canvas.drawPaint(mBackgroundPaint);
for(Box box:mBoxen){
if(mAngle!=null){ //mAngle存储的是angleBetweenLines方法中计算出的角度值
canvas.rotate(mAngle); //旋转画布
mAngle=null;
}
float leftX=Math.min(box.getCurrent().x,box.getOrigin().x);
float leftY=Math.min(box.getCurrent().y,box.getOrigin().y);
float rightX=Math.max(box.getCurrent().x,box.getOrigin().x);
float rightY=Math.max(box.getCurrent().y,box.getOrigin().y);
canvas.drawRect(leftX,leftY,rightX,rightY,mBoxPaint);
}
}
效果:
demo地址:https://github.com/zycoJamie/Rotate-Rectangle