旋转矩形框

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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值