【问题标题】:Android: How to rotate a view with one fingerAndroid:如何用一根手指旋转视图
【发布时间】:2013-12-24 09:35:51
【问题描述】:

我需要旋转一个有一些按钮的视图。随着手指的移动,视图也应该随着它的子视图一起旋转。

到目前为止,我已经实现了这个:

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);
}

但并不顺利,因此无法实现。

谢谢。

【问题讨论】:

    标签: android animation image-rotation


    【解决方案1】:

    首先,不要使用动画,因为您想在手指移动时直接更改视图。

    然后,对于计算,将 OnTouchListener 附加到要旋转的视图的父视图会容易得多,这样旋转本身就不会修改触摸事件的坐标。

    如果您有一个 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;
    }
    

    【讨论】:

    • 我尝试使用旋转,但我应该旋转多少度?当我使用 mCurrAngle 时它会变得一团糟
    • 您能描述一下当前的行为吗?
    • 当我顺时针移动时,它表现出异常行为。它同时顺时针和逆时针移动。
    • 尝试反转 atan2 中的参数,因为角度应该是 atan(y/x) -> Math.atan2(yc-y,x-xc)
    • 我设法通过创建父布局并将侦听器附加到它来使其工作。更简单的代码,无故障;)
    【解决方案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;
            }
        };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多