如何在 Android 中进行平滑的图像旋转?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1634252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:23:11  来源:igfitidea点击:

How to make a smooth image rotation in Android?

androidanimationview

提问by emmby

I'm using a RotateAnimationto rotate an image that I'm using as a custom cyclical spinner in Android. Here's my rotate_indefinitely.xmlfile, which I placed in res/anim/:

我正在使用 aRotateAnimation来旋转我在 Android 中用作自定义循环微调器的图像。这是我的rotate_indefinitely.xml文件,我放在res/anim/

<?xml version="1.0" encoding="UTF-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:duration="1200" />    

When I apply this to my ImageViewusing AndroidUtils.loadAnimation(), it works great!

当我将此应用于我的ImageViewusing 时AndroidUtils.loadAnimation(),效果很好!

spinner.startAnimation( 
    AnimationUtils.loadAnimation(activity, R.anim.rotate_indefinitely) );

The one problem is that the image rotation seems to pause at the top of every cycle.

一个问题是图像旋转似乎在每个循环的顶部暂停。

In other words, the image rotates 360 degrees, pauses briefly, then rotates 360 degrees again, etc.

换句话说,图像旋转 360 度,短暂暂停,然后再次旋转 360 度,等等。

I suspect that the problem is that the animation is using a default interpolator like android:iterpolator="@android:anim/accelerate_interpolator"(AccelerateInterpolator), but I don't know how to tell it not to interpolate the animation.

我怀疑问题在于动画使用了像android:iterpolator="@android:anim/accelerate_interpolator"( AccelerateInterpolator)这样的默认插值器,但我不知道如何告诉它不要对动画进行插值。

How can I turn off interpolation (if that is indeed the problem) to make my animation cycle smoothly?

如何关闭插值(如果这确实是问题所在)以使我的动画循环顺畅?

采纳答案by Bakhtiyor

You are right about AccelerateInterpolator; you should use LinearInterpolator instead.

你是对的 AccelerateInterpolator;您应该改用 LinearInterpolator。

You can use the built-in android.R.anim.linear_interpolatorfrom your animation XML file with android:interpolator="@android:anim/linear_interpolator".

您可以使用android.R.anim.linear_interpolator动画 XML 文件中的内置文件android:interpolator="@android:anim/linear_interpolator"

Or you can create your own XML interpolation file in your project, e.g. name it res/anim/linear_interpolator.xml:

或者您可以在您的项目中创建您自己的 XML 插值文件,例如将其命名为res/anim/linear_interpolator.xml

<?xml version="1.0" encoding="utf-8"?>
<linearInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />

And add to your animation XML:

并添加到您的动画 XML:

android:interpolator="@anim/linear_interpolator"

Special Note:If your rotate animation is inside a set, setting the interpolator does not seem to work. Making the rotate the top element fixes it. (this will save your time.)

特别注意:如果您的旋转动画在一个集合内,则设置插值器似乎不起作用。使旋转顶部元素修复它。(这将节省您的时间。)

回答by Rabs G

I had this problem as well, and tried to set the linear interpolator in xml without success. The solution that worked for me was to create the animation as a RotateAnimation in code.

我也有这个问题,并试图在 xml 中设置线性插值器但没有成功。对我有用的解决方案是在代码中将动画创建为 RotateAnimation。

RotateAnimation rotate = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(5000);
rotate.setInterpolator(new LinearInterpolator());

ImageView image= (ImageView) findViewById(R.id.imageView);

image.startAnimation(rotate);

回答by Luis E. Fernandez

This works fine

这工作正常

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="358" />

To reverse rotate:

反向旋转:

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="358"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="0" />

回答by Fernando Gallego

Try using toDegrees="359"since 360° and 0° are the same.

尝试使用,toDegrees="359"因为 360° 和 0° 是相同的。

回答by Vitaly Zinchenko

Maybe, something like this will help:

也许,这样的事情会有所帮助:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        imageView.animate().rotationBy(360).withEndAction(this).setDuration(3000).setInterpolator(new LinearInterpolator()).start();
    }
};

imageView.animate().rotationBy(360).withEndAction(runnable).setDuration(3000).setInterpolator(new LinearInterpolator()).start();

By the way, you can rotate by more than 360 like:

顺便说一下,您可以旋转超过 360 度,例如:

imageView.animate().rotationBy(10000)...

回答by Ashraf Rahman

ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).setDuration(300).start();

Try this.

尝试这个。

回答by Geet Thakur

Rotation Object programmatically.

以编程方式旋转对象。

// clockwise rotation :

// 顺时针旋转:

    public void rotate_Clockwise(View view) {
        ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 180f, 0f);
//        rotate.setRepeatCount(10);
        rotate.setDuration(500);
        rotate.start();
    }

// AntiClockwise rotation :

// 逆时针旋转 :

 public void rotate_AntiClockwise(View view) {
        ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 0f, 180f);
//        rotate.setRepeatCount(10);
        rotate.setDuration(500);
        rotate.start();
    } 

viewis object of your ImageView or other widgets.

视图是您的 ImageView 或其他小部件的对象。

rotate.setRepeatCount(10);use to repeat your rotation.

旋转.setRepeatCount(10); 用于重复您的旋转。

500is your animation time duration.

500是您的动画持续时间。

回答by Christopher Stock

Pruning the <set>-Element that wrapped the <rotate>-Element solves the problem!

修剪<set>包装<rotate>-Element 的 -Element 解决了问题!

Thanks to Shalafi!

感谢沙拉菲!

So your Rotation_ccw.xml should loook like this:

所以你的 Rotation_ccw.xml 应该是这样的:

<?xml version="1.0" encoding="utf-8"?>

<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="2000"
    android:fillAfter="false"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:interpolator="@android:anim/linear_interpolator"
    />

回答by Rahul Agrawal

As hanry has mentioned above putting liner iterpolator is fine. But if rotation is inside a set you must put android:shareInterpolator="false" to make it smooth.

正如 hanry 上面提到的,放置线性迭代器很好。但是如果旋转在一个集合内,你必须把 android:shareInterpolator="false" 让它平滑。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
**android:shareInterpolator="false"**
>
<rotate
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="300"
    android:fillAfter="true"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%" />
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="3000"
    android:fillAfter="true"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="0"
    android:toYScale="0" />
</set>

If Sharedinterpolator being not false, the above code gives glitches.

如果 Sharedinterpolator 不为 false,则上述代码会出现故障。

回答by ununiform

No matter what I tried, I couldn't get this to work right using code (and setRotation) for smooth rotation animation. What I ended up doing was making the degree changes so small, that the small pauses are unnoticeable. If you don't need to do too many rotations, the time to execute this loop is negligible. The effect is a smooth rotation:

无论我尝试过什么,我都无法使用代码(和 setRotation)来使平滑旋转动画正常工作。我最终做的是使度数变化如此之小,以至于微小的停顿都无法察觉。如果不需要做太多的旋转,执行这个循环的时间可以忽略不计。效果是平滑旋转:

        float lastDegree = 0.0f;
        float increment = 4.0f;
        long moveDuration = 10;
        for(int a = 0; a < 150; a++)
        {
            rAnim = new RotateAnimation(lastDegree, (increment * (float)a),  Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            rAnim.setDuration(moveDuration);
            rAnim.setStartOffset(moveDuration * a);
            lastDegree = (increment * (float)a);
            ((AnimationSet) animation).addAnimation(rAnim);
        }