安卓 ImageView 动画

65

我创建了一个布局,其中包含 ImageView(图像视图) 和 WebView(Web 视图)。WebView 设置默认可见性为“gone”(隐藏)。当 Activity 启动时,它首先显示 ImageView;当 WebView 加载完其 URL 时,将自己标记为可见并将 ImageView 标记为隐藏。

当 ImageView 显示时,我希望它重复旋转,以增加一些视觉效果。

我以前从未在 Android 中进行过动画处理,而且当我在互联网上搜索时发现的所有帖子都没有帮助。因此,我回到 SO 寻求帮助。

那么,如果我从这里开始……

    final ImageView splash = (ImageView)findViewById(R.id.splash);

我如何创建重复的旋转动画并将其应用于 ImageView?

再次感谢!

9个回答

110

使用RotateAnimation,将旋转中心点设置为图像中心。

RotateAnimation anim = new RotateAnimation(0f, 350f, 15f, 15f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(700);

// Start animating the image
final ImageView splash = (ImageView) findViewById(R.id.splash);
splash.startAnimation(anim);

// Later.. stop the animation
splash.setAnimation(null);

5
如何设置相对旋转轴点:new RotateAnimation(0f, 350f, 15f, 15f);或者我需要先检查屏幕是ldpi、mdpi或hdpi,再根据比例因子调整旋转轴的值吗?我还注意到,我的图片没有返回到原始位置,不像原生的安卓spinner。(我想在一个图像视图中使用默认的安卓spinner,并使其看起来与原本的一样。) - OneWorld
1
和OneWorld一样的问题。我没有方便的旋转,因为即使我将旋转中心的坐标定义为splash.getWidth()和splash.getHeight()的一半,它们也不正确。如何解决这个问题? - toto_tata

53

如何围绕图像中心旋转:

ImageView view = ... //Initialize ImageView via FindViewById or programatically

RotateAnimation anim = new RotateAnimation(0.0f, 360.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

//Setup anim with desired properties
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE); //Repeat animation indefinitely
anim.setDuration(700); //Put desired duration per anim cycle here, in milliseconds

//Start animation
view.startAnimation(anim); 
//Later on, use view.setAnimation(null) to stop it.

这将导致图像围绕其中心旋转(宽度/高度的0.5或50%)。我是为了未来从Google等搜索引擎到达此处并希望在不定义绝对像素中心的情况下围绕图像中心旋转的读者发布此内容。


3
这很符合我的要求。我唯一需要更改的是将“Dimension.RelativeToSelf”指定为“Animation.RELATIVE_TO_SELF”。 - Guru

25

你还可以直接使用旋转动画功能。它会对 ImageView 执行一个特定的动画,持续一段预定的时间。

Animation rotate = AnimationUtils.loadAnimation([context], R.anim.rotate_picture);
splash.startAnimation(rotate);

然后在你的res/anim中创建一个名为rotate_picture的动画XML文件,其内容如下:

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

    <rotate 
    android:fromDegrees="0"
    android:toDegrees="360"
    android:duration="5000"
    android:pivotX="50%"
    android:pivotY="50%">
</rotate>
</set>

不幸的是,这只会运行一次。你需要在某个地方添加循环,使其在等待时重复动画。我做了一些实验,导致程序陷入无限循环,所以我不确定最好的方法是什么。编辑:Christopher的答案提供了如何正确循环的信息,因此删除了我有关单独线程的错误建议!


1
你不能添加 android:repeatCount="infinite" 吗?或者可以使用 rotate.setRepeatCount(Animation.INFINITE) - Peter Ajtai
我非常喜欢这个解决方案:将其抽象为XML会更加优美。 - RichieHH

11

一种方法是将您的图像分成N个部分,每次略微旋转。我建议使用5个部分就足够了。 然后在drawable中创建类似于以下内容的东西:

<animation-list   android:id="@+id/handimation" android:oneshot="false" 
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/progress1" android:duration="150" />
    <item android:drawable="@drawable/progress2" android:duration="150" />
    <item android:drawable="@drawable/progress3" android:duration="150" />
 </animation-list> 

代码开始

progress.setVisibility(View.VISIBLE);
AnimationDrawable frameAnimation = (AnimationDrawable)progress.getDrawable();
frameAnimation.setCallback(progress);
frameAnimation.setVisible(true, true);

代码停止

AnimationDrawable frameAnimation = (AnimationDrawable)progress.getDrawable();
frameAnimation.stop();
frameAnimation.setCallback(null);
frameAnimation = null;
progress.setVisibility(View.GONE);

更多信息请点击这里


感谢您记录这个解决方案。虽然其他人提供的旋转答案适合原始问题的目的,但您的解决方案正是我寻找的以其他方式进行动画的方法。 - CodeChimp
1
当已经有旋转动画时,这将是实现所需目标的可怕方式。为什么要手动完成所有操作:会产生巨大的资源存储开销。 - RichieHH

7
imgDics = (ImageView) v.findViewById(R.id.img_player_tab2_dics);
    imgDics.setOnClickListener(onPlayer2Click);
    anim = new RotateAnimation(0f, 360f,
            Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                            0.5f);
    anim.setInterpolator(new LinearInterpolator());
    anim.setRepeatCount(Animation.INFINITE);
    anim.setDuration(4000);

    // Start animating the image
    imgDics.startAnimation(anim);

从“SELF”的旋转方面来看,听起来不错,对我来说效果很好。 (+1) - Anuj

6

在 <head> 元素中添加以下内容:

android:repeatCount="infinite"

3

我发现如果你使用.getWidth/2等方法是行不通的,你需要自己获取图片的像素数并除以2,然后只需为最后两个参数键入数字。

比如说你的图片是一个120像素×120像素的正方形,那么你的x和y坐标应该是60像素。 在你的代码中,你应该这样写:

RotateAnimation anim = new RotateAnimation(0f, 350f, 60f, 60f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(700);

现在,您的图像将围绕其中心旋转。

2

已验证代码:

imageView.setImageResource(R.drawable.ic_arrow_up);

boolean up = true;

if (!up) { 
    up = true; 
    imageView.startAnimation(animate(up)); 
} else { 
    up = false; 
    imageView.startAnimation(animate(up)); 
}

private Animation animate(boolean up) {
    Animation anim = AnimationUtils.loadAnimation(this, up ? R.anim.rotate_up : R.anim.rotate_down);
    anim.setInterpolator(new LinearInterpolator()); // for smooth animation
    return anim;
}

drawable/ic_arrow_up.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#3d3d3d"
        android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>

anim/rotate_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:fillEnabled="true">
    <rotate
        android:duration="200"
        android:fromDegrees="-180"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="0" />
</set>

anim/rotate_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:fillEnabled="true">
    <rotate
        android:duration="200"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="180" />
</set>

0

不要硬编码图像边界。只需使用:

RotateAnimation anim = new RotateAnimation( fromAngle, toAngle, imageView.getDrawable().getBounds().width()/2, imageView.getDrawable().getBounds().height()/2);

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