Android里的动画分为两类,以3.0版本为分水岭。
3.0前已存在
- 帧动画
- 补间动画
3.0出现
- 属性动画
帧动画
顾名思义,快速切换几张图片来达到动画的效果。
建立帧动画xml
Note:不要把这个帧动画文件放到anim文件夹中,要放到drawable文件夹中
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100"></item>
<item
android:drawable="@drawable/a_1"
android:duration="200"></item>
<item
android:drawable="@drawable/a_2"
android:duration="300"></item>
</animation-list>
java中启动动画
public class FrameAnimActivity extends AppCompatActivity {
private ImageView iv_anim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame);
initView();
}
private void initView() {
iv_anim = (ImageView) findViewById(R.id.iv_anim);
iv_anim.setImageResource(R.drawable.frame_anim);
AnimationDrawable animationDrawable = (AnimationDrawable) iv_anim.getDrawable();
animationDrawable.start();
}
}
android:oneshot=”false” ,这个oneshot 的含义就是动画执行一次(true)还是循环执行多次。
补间动画 Tweened Animation
alpha 淡入淡出
XML声明动画
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="0.0"/>
Note:AS的自动补全对除了fromAlpha及toAlpha均不予默认支持,但是如duration,interpolator仍旧是存在的。
Java中启动动画
ImageView iv_alpha_cat = (ImageView) findViewById(R.id.iv_alpha_cat);
Animation alphaCat = AnimationUtils.loadAnimation(this, R.anim.anim_alpha_cat);
iv_alpha_cat.startAnimation(alphaCat);
translate 平移
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="300"
android:fromYDelta="300"
android:toXDelta="0"
android:toYDelta="0">
</translate>
- 无论是fromXDelta还是toXDelta的值都是**相对**View原始位置的X,Y距离。
- 如果不加android:duration ,动画是不执行的。
rotate 旋转
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromDegrees="0"
android:pivotX="10%"
android:pivotY="10%"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toDegrees="60">
</rotate>
scale 缩放
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXScale="1.5"
android:toYScale="1.5"
>
</scale>
动画集合
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toAlpha="0.0"/>
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="10%"
android:pivotY="10%"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toDegrees="60">
</rotate>
<scale
android:duration="1000"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXScale="1.5"
android:toYScale="1.5"
>
</scale>
<translate
android:duration="1000"
android:fromXDelta="300"
android:fromYDelta="300"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXDelta="0"
android:toYDelta="0">
</translate>
</set>
几个公用的属性
糟糕的是,as下不会自动提示或补全这些属性,所以得自己记住。
重复性设置
android:repeatCount="infinite"
android:repeatMode="reverse"
轴心点设置
android:pivotX="10%"
android:pivotY="10%"
速率设置 Interpolator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
间隔时间 startOffset
动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间
属性动画
iv_alpha_cat = (ImageView) findViewById(R.id.iv_alpha_cat);
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(iv_alpha_cat, "alpha", 0, 0.9f);
alphaAnimator.setDuration(1000);
alphaAnimator.setRepeatCount(ValueAnimator.INFINITE);
alphaAnimator.setRepeatMode(ValueAnimator.REVERSE);
alphaAnimator.start();
iv_trans_cat = (ImageView) findViewById(R.id.iv_trans_cat);
ObjectAnimator transAnimator = ObjectAnimator transAnimator = ObjectAnimator.ofFloat(iv_trans_cat, "translationX", 400, 0, 300, 0, 200);
transAnimator.setDuration(1000);
transAnimator.setRepeatCount(ValueAnimator.INFINITE);
transAnimator.setRepeatMode(ValueAnimator.REVERSE);
transAnimator.start();
如上是实现渐变及平移的代码。
* 有意思的是,在平移的动画操作中,设置多个值的时候,动画会在多个位置值中移动,如上 200->0->400 居然能变成弹跳的效果。
其他及组合实现
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 0.0f, 2.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(myView, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(myView, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(myView, "tranlsationY", 100, 750);
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
// set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();
属性动画 补间及帧动画 优与劣
从上面两幅图比较可以发现,补间动画中,虽然使用translate将图片移动了,但是点击原来的位置,依旧可以发生点击事件,而属性动画却不是。因此我们可以确定,属性动画才是真正的实现了view的移动,补间动画对view的移动更像是在不同地方绘制了一个影子,实际的对象还是处于原来的地方。
当我们把动画的repeatCount设置为无限循环时,如果在Activity退出时没有及时将动画停止,属性动画会导致Activity无法释放而导致内存泄漏,而补间动画却没有问题。因此,使用属性动画时切记在Activity执行 onStop 方法时顺便将动画停止。(对这个怀疑的同学可以自己通过在动画的Update 回调方法打印日志的方式进行验证)。
xml 文件实现的补间动画,复用率极高。在Activity切换,窗口弹出时等情景中有着很好的效果。
使用帧动画时需要注意,不要使用过多特别大的图,容易导致内存不足。