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

时间:2016-08-31 22:23:22

标签: android animation rotation android-animation

我目前正在开发一个应用程序,其中我想指出一个带箭头的路径(它就像一个指南针)。

为了将箭头移动到正确的方向,我使用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 个答案:

答案 0 :(得分:6)

如果参数toDegrees大于参数fromDegrees,RotationAnimation对象将顺时针转动。你必须自己处理这样一个事实:你不想从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+创建一个应用程序来使用animate()这样的View方法:

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

对于后来问过的人来说,这是一个受@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);
        }
    }

答案 3 :(得分:0)

每次箭头都以不同的方式旋转。您可以选择其他角度。别忘了负角也是可用的。

您可以像这样使用animate()

if (view==button1) {
            arrowImage.animate().rotation(0).start();
        } else {
            arrowImage.animate().rotation(-90).start();
        }