开发者社区> 问答> 正文

缩放TextView 问问题

我正在编写一个组件来处理缩放,旋转和平移的手势识别。令人遗憾的是,缩放不起作用,它没有收到缩小,并且放大效果不好,因为当视图很大时,它什么也没做,似乎只有在到达视图边缘时才起作用。

public class MyGestureDetector implements ScaleGestureDetector.OnScaleGestureListener {
    private static final int INVALID_POINTER_ID = -1;
    private float fX, fY, sX, sY;
    private int ptrID1, ptrID2;
    private float mAngle;
    private float mPreviousAngle = 0;
    private float mDeltaAngle;

    private float dX, dY;
    private boolean isClick, isMove;
    private float mRatio = 1.0f;
    private int mBaseDist;
    private float mBaseRatio;
    private final static float STEP = 200;

    private Vector2D movement = new Vector2D();
    private Vector2D movementRaw = new Vector2D();
    private ScaleGestureDetector mScaleGestureDetector;


    private OnGestureListener mListener;

    public float getAngle() {
        return mAngle;
    }

    public float getScaling() {
        return mRatio;
    }

    public Vector2D getMovement() {
        return movement;
    }
    public Vector2D getMovementRaw() {
        return movementRaw;
    }
    private ScaleGestureDetector gestureScale;
    private float scaleFactor = 1;
    private boolean inScale = false;

    public MyGestureDetector(OnGestureListener listener){
        gestureScale = new ScaleGestureDetector((Context) listener, this);
        mListener = listener;
        ptrID1 = INVALID_POINTER_ID;
        ptrID2 = INVALID_POINTER_ID;
    }

    public boolean onTouchEvent(MotionEvent event, View view){
        gestureScale.onTouchEvent(event);
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:

                isClick=true;
                isMove=true;
                dX = view.getX() - event.getRawX();
                dY = view.getY() - event.getRawY();
                currentPosition = new Vector2D(event.getRawX(), event.getRawY());


                ptrID1 = event.getPointerId(event.getActionIndex());

                break;
            case MotionEvent.ACTION_POINTER_DOWN:

                if(ptrID2 == INVALID_POINTER_ID ) {


                    ptrID2 = event.getPointerId(event.getActionIndex());

                    int pt1 = event.findPointerIndex(ptrID1);
                    int pt2 = event.findPointerIndex(ptrID2);
                    if(pt1 < 0 || pt2 < 0 ){
                        return false;
                    }

                    mBaseDist = getDistance(event);
                    mBaseRatio = mRatio;

                    startX = event.getRawX() - view.getX() + centerX;
                    startY = event.getRawY() - view.getY() + centerY;

                    sX = event.getX(pt1);
                    sY = event.getY(pt1);
                    fX = event.getX(pt2);
                    fY = event.getY(pt2);

                    isClick=false;
                    isMove=false;
                }

                break;
            case MotionEvent.ACTION_MOVE:
                if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID) {

                    int pt1 = event.findPointerIndex(ptrID1);
                    int pt2 = event.findPointerIndex(ptrID2);
                    if(pt1 < 0 || pt2 < 0 ){
                        return false;
                    }
                    /// Scaling
                    float delta = (getDistance(event) - mBaseDist) / STEP;
                    float multi = (float) Math.pow(2, delta);
                    //mRatio = Math.min(10.0f, Math.max(0.5f, mBaseRatio * multi));

                    /// Rotating
                    float nfX, nfY, nsX, nsY;



                    nsX = event.getX(pt1);
                    nsY = event.getY(pt1);
                    nfX = event.getX(pt2);
                    nfY = event.getY(pt2);

                    if(nsX < 0 || nsY < 0 || nfX < 0 || nfY < 0){
                        return false;
                    }

                    mAngle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY);
                    mDeltaAngle = mAngle - mPreviousAngle;

                    if (mListener != null) {
                        mPreviousAngle = mAngle;
                        mListener.OnRotation(this);
                        //mListener.OnScaling(this);
                    }



                }else{

                    if(!currentPosition.toString().equals(new Vector2D(event.getRawX(), event.getRawY()).toString())){
                        isClick=false;
                    }

                    currentPosition = new Vector2D(event.getRawX(), event.getRawY());
                    movement.set(event.getRawX() + dX, event.getRawY() + dY);
                    movementRaw.set(event.getRawX() , event.getRawY() );
                    if (isMove && mListener != null) {
                        mListener.OnMove(this);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:

                if(isClick) {
                    if (mListener != null) {
                        mListener.OnClick(this);
                    }
                }else{
                    mListener.OnStopGesture(this);

                }
                ptrID1 = INVALID_POINTER_ID;

                break;
            case MotionEvent.ACTION_POINTER_UP:
                ptrID2 = INVALID_POINTER_ID;
                break;
            case MotionEvent.ACTION_CANCEL:
                ptrID1 = INVALID_POINTER_ID;
                ptrID2 = INVALID_POINTER_ID;
                break;
        }
        return true;
    }




    int getDistance(MotionEvent event) {
        int dx = (int) (event.getX(0) - event.getX(1));
        int dy = (int) (event.getY(0) - event.getY(1));
        return (int) (Math.sqrt(dx * dx + dy * dy));
    }

    float centerX, centerY, startR, startScale, startX, startY, startRotation, startA;
    TextView tv;
    Vector2D currentPosition;


    private float angleBetweenLines (float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY)
    {
        float angle1 = (float) Math.atan2( (fY - sY), (fX - sX) );
        float angle2 = (float) Math.atan2( (nfY - nsY), (nfX - nsX) );

        float angle = ((float)Math.toDegrees(angle1 - angle2)) % 360;
        if (angle < -180.f) angle += 360.0f;
        if (angle > 180.f) angle -= 360.0f;
        return angle;
    }


    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        scaleFactor *= scaleGestureDetector.getScaleFactor();
        //scaleFactor = (scaleFactor < 1 ?  : scaleFactor); // prevent our view from becoming too small //
        scaleFactor = ((float)((int)(scaleFactor * 100))) / 100; // Change precision to help with jitter when user just rests their fingers //
        mRatio = scaleFactor;

        if (mListener != null) {
            mListener.OnScaling(this);
        }
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
        inScale = true;
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
        inScale = false;
    }

    public static interface OnGestureListener {
        public void OnRotation(MyGestureDetector rotationDetector);
        public void OnScaling(MyGestureDetector rotationDetector);
        public void OnMove(MyGestureDetector rotationDetector);
        public void OnClick(MyGestureDetector rotationDetector);
        public void OnStopGesture(MyGestureDetector rotationDetector);

    }

}

展开
收起
垚tutu 2019-12-09 09:51:45 634 0
0 条回答
写回答
取消 提交回答
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载