Android: 如何选择RotateAnimation的旋转方向?

4

我目前正在开发一个应用程序,希望用箭头(类似指南针)来指示路径。

为了将箭头移动到正确的方向,我使用了RotateAnimation类。它的效果非常好,但是当初始角度位置与最终角度位置相差很大时,旋转不会选择更快的方式。

在这个视频中,你可以看到这种行为:https://youtu.be/vypZni_1s3I

以下是用户点击“02”按钮时执行的代码:

RotateAnimation rotateAnimation = new RotateAnimation(355f, 8f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);

当用户点击“03”按钮时执行的代码如下:

RotateAnimation rotateAnimation = new RotateAnimation(8f, 350f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);

如您在视频中所见,旋转并没有选择更快的方式。在第一个动画中,更快的方式是顺时针旋转(但系统选择了逆时针旋转),在第二个动画中,更快的方式是逆时针旋转(但系统选择了顺时针旋转)。

是否有解决方案或技巧可以强制系统选择更快的方式以从点A旋转到点B?

4个回答

13

如果参数toDegrees大于参数fromDegreesRotationAnimation对象将逆时针旋转。你需要自己处理实际上你不想从355f8f,而是从355f368f(即360度加8度)的事实。

因此,在这里,您需要将您的两段代码更改如下:

RotateAnimation rotateAnimation = new RotateAnimation(355f, 368f, 
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);

RotateAnimation rotateAnimation = new RotateAnimation(368f, 350f, 
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);

但我建议,如果您想使用API 14+创建应用程序,则可以使用Viewanimate()方法,如下所示:

test.animate()
  .rotationBy(13f)
  .setDuration(3000)
  .setInterpolator(new LinearInterpolator())
  .start();

rotationBy(offset) 方法将以中心轴为旋转点,将您的视图旋转 offset 度,如果 offset 为正,则顺时针旋转,否则逆时针旋转。


4

+1 @MaximeClaude的回答是正确的,但可以大大简化:

//declarations
private static final int HALF_CIRCLE = 180;
private static final int WHOLE_CIRCLE = 360;
private float currentAzimuth = 0f;

public void rotate(float rotationDegrees, View... views) {
    float from = currentAzimuth;
    float to = rotationDegrees;
    float min = Math.min(from, to);
    if (Maths.abs(to - from) > HALF_CIRCLE) {
        if (min == from) {
            from += WHOLE_CIRCLE;
        } else {
            to += WHOLE_CIRCLE;
        }
    }
    currentAzimuth = rotationDegrees;

    Animation anim = new RotateAnimation(from, to, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    anim.setFillAfter(true); //make the arrow stay at its destination (after rotation)
    anim.setDuration(200);
    for (View view : views) {
        view.startAnimation(anim);
    }
}

使用 android.view.OrientationEventListener 来设置视图方向:
mOrientationEventListener = new OrientationEventListener(context) {
    @Override
    public void onOrientationChanged(int orientation) {
        rotate(orientation, arrowView);
    }
};

1

如果有人后来问起,这是一个通用案例,灵感来自@David Fournier的答案:

//declarations
    private static final int HALF_CIRCLE = 180;
    private static final int WHOLE_CIRCLE = 360;
    private float azimuth = 0f;
    private float currenttAzimuth = 0f;

    /**
     * "will set rotation from " + currentAzimuth + " to " + azimuth
     */
    public void rotate(Double bearing){
        if(bearing != null) {
            azimuth  = (float)bearing.doubleValue();
            float min = Math.min(azimuth,currenttAzimuth);

            float tempAzimuth = 0.0f;
            float tempCurrentAzimuth = 0.0f;

            Animation rotateAnim = null;
            if(Math.abs(azimuth - currenttAzimuth) > HALF_CIRCLE) {
                if(min == currenttAzimuth) {
                    tempCurrentAzimuth = currenttAzimuth + WHOLE_CIRCLE;
                    tempAzimuth = azimuth;
                }
                else {
                    tempCurrentAzimuth = currenttAzimuth ;
                    tempAzimuth = azimuth + WHOLE_CIRCLE;
                }
                rotateAnim = new RotateAnimation(tempCurrentAzimuth, tempAzimuth,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
            }
            else {
                rotateAnim = new RotateAnimation(currenttAzimuth, azimuth,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
            }
            currenttAzimuth = azimuth;
            rotateAnim.setFillAfter(true); //make the arrow stay at its destination (after rotation)
            rotateAnim.setDuration(500);
            arrowView.startAnimation(rotateAnim);
        }
    }

0
每次箭头都会旋转到不同的方向。您可以选择不同的角度。不要忘记负角度也是可用的。
您可以像这样使用animate():
if (view==button1) {
            arrowImage.animate().rotation(0).start();
        } else {
            arrowImage.animate().rotation(-90).start();
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接