Android: How to rotate a view with one finger

╄→尐↘猪︶ㄣ 提交于 2019-12-23 18:34:40

问题


I need to rotate a view which have some buttons. With the finger movement, view should also rotate along with it's child views accordingly.

Till now I have implemented this:

private RelativeLayout mCircle;
private double mCurrAngle = 0;
private double mPrevAngle = 0;
int i = 0;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mCircle = (RelativeLayout) findViewById(R.id.circle);
    mCircle.setOnTouchListener(this); // Your activity should implement
                                        // OnTouchListener
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    final float xc = mCircle.getWidth() / 2;
    final float yc = mCircle.getHeight() / 2;

    final float x = event.getX();
    final float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        mCircle.clearAnimation();
        mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
        break;
    }
    case MotionEvent.ACTION_MOVE: {
        mPrevAngle = mCurrAngle;
        mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
        mCircle.setRotation((float) (mPrevAngle - mCurrAngle));         

        animate(mPrevAngle, mCurrAngle, 0);
        break;
    }
    case MotionEvent.ACTION_UP: {
        mPrevAngle = mCurrAngle = 0;
        break;
    }
    }

    return true;
}

private void animate(double fromDegrees, double toDegrees,
        long durationMillis) {
    final RotateAnimation rotate = new RotateAnimation((float) fromDegrees,
            (float) toDegrees, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    rotate.setDuration(durationMillis);
    rotate.setFillEnabled(true);
    rotate.setFillAfter(true);
    mCircle.startAnimation(rotate);
}

But it is not smooth and thus can't be implemented.

Thanks.


回答1:


First, do not use animation, as you want to directly change the view as the finger moves.

Then, for the computations, it is a lot easier to attach the OnTouchListener to a parent view of the view you want to rotate, so that the coordinate of your touch event is not modified by the rotation itself.

Here is the code if you have a parent view with id "@+id/root":

private RelativeLayout mRoot;
private RelativeLayout mCircle;
int i = 0;
float viewRotation;
double fingerRotation;
double newFingerRotation;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mRoot = (RelativeLayout)findViewById(R.id.root);
     mCircle = (RelativeLayout) findViewById(R.id.circle);
     mRoot.setOnTouchListener(this);
}

@Override
public boolean onTouch(View v, MotionEvent event) {

    final float x = event.getX();
    final float y = event.getY();

    final float xc = mRoot.getWidth()/2;
    final float yc = mRoot.getHeight()/2;

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            viewRotation = mCircle.getRotation();
            fingerRotation = Math.toDegrees(Math.atan2(x - xc, yc - y));
            break;
        case MotionEvent.ACTION_MOVE:
            newFingerRotation = Math.toDegrees(Math.atan2(x - xc, yc - y));
            mCircle.setRotation((float)(viewRotation + newFingerRotation - fingerRotation));
            break;
        case MotionEvent.ACTION_UP:
            fingerRotation = newFingerRotation = 0.0f;
            break;
    }

    return true;
}



回答2:


        @Override
        public boolean onTouch(View view, MotionEvent event) {  

             switch (action) {
                    case MotionEvent.ACTION_UP:
                        break;
                    case MotionEvent.ACTION_DOWN:

                        rotateX = event.getRawX();
                        rotateY = event.getRawY();

                        centerX = view.getX() + ((View) getParent()).getX() + (float) view.getWidth() / 2;

                        centerY = view.getY() + statusBarHeight + (float) view.getHeight() / 2;

                        break;

                    case MotionEvent.ACTION_MOVE:

                        newRotateX = event.getRawX();
                        newRotateY = event.getRawY();

                        double angle = Math.atan2(event.getRawY() - centerY, event.getRawX() - centerX) * 180 / Math.PI;

                        view.setRotation((float) angle - 45);

                        rotateX = newRotateX;
                        rotateY = newRotateY;
                }
            }

            return true;
        }
    };


来源:https://stackoverflow.com/questions/20758365/android-how-to-rotate-a-view-with-one-finger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!