简介
Android中的动画大致分为三类:view动画、帧动画、属性动画。
view动画
又叫补间动画。支持四种动画操作,分别是平移动画、旋转动画、缩放动画、透明度动画,当让也可以设置动画集,里面添加任意个四种动画操作。
原理:通过父容器来绘制自己动画时的样子;实际上自己本身没有进行动画,自身还在原先的位置上没有改变。
作用对象:View
使用:
- 通过XML文件定义
- 在res目录中创建anim文件,在该文件中创建XML文件
- 使用的标签是<set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fromXDelta="500"
android:toXDelta="0" />
</set>
在代码中使用
Button button = (Button) findViewById(R.id.hello);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.myanimation);
button.startAnimation(animation);
在代码中创建
Button button = (Button) findViewById(R.id.hello);
AlphaAnimation animation = new AlphaAnimation(0, 1);
animation.setDuration(300);
button.startAnimation(animation);
分类
- AlphaAnimation:渐变动画,从无到有
- RotateAnimation:旋转动画
- ScaleAnimation:比例动画,从小到大
- TranslateAnimation:位移动画
- AnimationSet:动画集合(包含多个动画)
特殊应用:使用LayoutAnimation作用于ViewGroup,为其制定一个动画,这样他所有的子元素具有这种动画效果
1、定义动画(指定子元素的入场动画)<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:shareInterpolator="true">
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"/>
<translate android:fromXDelta="500"
android:toXDelta="0"/>
</set>
2、定义layoutAnimation
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_item">
</layoutAnimation>
3、设置ViewGroup的属性
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layout"
android:background="#fff4f7f9"
android:cacheColorHint="#00000000"
android:divider="#dddbdb"
android:dividerHeight="1.0dp"
android:listSelector="@android:color/transparent">
</ListView>
也可以在代码中实现(通过使用LayoutAnimationController实现)
ListView listView = (ListView) findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);
Activity的切换效果(使用overridePendingTransition(int enterAnim, int exitAnim))
- enterAnim:Activity 被打开时所需要的动画资源id
- exitAnim:Activity 被关闭时所需要的动画资源id
- overridePendingTransition()方法必须在startActivity或者finish之后,否则没有效果
Intent intent = new Intent(MainActivity.this, Demo01.class);
startActivity(intent);
overridePendingTransition(R.anim.anim_enter, R.anim.anim_exit);
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.anim_enter, R.anim.anim_exit);
}
Fragment添加动画
通过FragmentTransaction中的setCustomAnimation()方法设置切换效果
属性动画
Property Animation。在一个时间间隔内完成对象从一个属性值到另一个属性值的改变原理:通过改变自身的属性来显示动画;自身真正的动了起来。
分类
- ObjectAnimator
- ValueAnimator
- AnimatorSet
public void translate(View view){
//arg0:要操作的对象;arg1:要修改的属性的名字
ObjectAnimator oa1 = ObjectAnimator.ofFloat(imageView, "translationX", 0, 30,70,120);
//定义动画持续时间
oa1.setDuration(2000);
//设置重复播放次数
oa1.setRepeatCount(2);
//设置重复模式
oa1.setRepeatMode(ValueAnimator.REVERSE);
//播放动画
oa1.start();
}
动画集
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(view, "rotationX", 0, 360),
ObjectAnimator.ofFloat(view, "rotationY", 0, 180),
ObjectAnimator.ofFloat(view, "rotation", 0, -90),
ObjectAnimator.ofFloat(view, "translationX", 0, 90),
ObjectAnimator.ofFloat(view, "translationY", 0, 90),
ObjectAnimator.ofFloat(view, "scaleX", 0, 1.5f),
ObjectAnimator.ofFloat(view, "scaleY", 0, 0.5f),
ObjectAnimator.ofFloat(view, "alpha", 1, 0.25f,1)
);
set.setDuration(5*1000).start();
属性动画中两个重要概念:
* 插值器——根据时间流逝的百分比计算出当前属性值改变的百分比
* LinearInterpolator(线性插值器:匀速动画)
* AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)
* DecelerateInterpolator(减速插值器:动画越来越慢)
* 估值器——根据当前属性改变的百分比计算出改变后的属性
* IntEvaluator(针对整型属性)
* FloatEvaluator(针对浮点型属性)
* ArgbEvaluator(针对Color属性)
* 自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值算法需要实现TypeEvaluator
属性动画的监听器:
- AnimationListener
- AnimatorListenerAdapter:AnimationListener的适配器,可以选择性的实现自己需要的方法
- AnimatorUpdateListener:监听动画的整个过程,动画每播放一帧就会调用一次(默认每20ms一帧)
属性动画要求动画作用的对象提供该属性的get和set方法:
- 对象必须提供set**方法,如果动画的时候没有传递初始值,那么还需要提供get**方法,因为系统要去获取对象的**属性初始值(该条不满足程序直接crash)
- 对象的set**对属性**所做的改变必须能够通过某种方法反映出来,比如会带来UI的改变之类(该条不满足,动画无效果但不会crash)
- 如果有权限的话,给对象加上get和set方法
- 用一个类包装原始对象,间接为其提供get和set方法
//调用performAnimate()方法即可实现mView对象在5秒内宽度变为500
private void performAnimate(){
ViewWrapper wrapper = new ViewWrapper(mView);
ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}
//自定义的类封装原始对象并提供了该对象的宽度的set和get方法
private static class ViewWrapper{
private View mTarget;
public ViewWrapper(View target) {
mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
采用ValueAnimator,监听动画过程,自己实现属性的改变
//调用该方法可以实现对象在5秒内宽度变为500
private void performAnimate(final View target, final int start, final int end) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private IntEvaluator mEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获取当前动画的进度值(1-100之间)
int currentValue = (int) animation.getAnimatedValue();
//获取当前进度占整个动画过程的比例(0-1之间)
float fraction = animation.getAnimatedFraction();
//直接调用整型估值器,通过比例计算出宽度,再将该值设置给被操作的 View
target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}
帧动画
Drawable Animation,多张图片快速切换,形成动画效果<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@drawable/pic1"
android:duration="500"/>
<item
android:drawable="@drawable/pic2"
android:duration="500"/>
<item
android:drawable="@drawable/pic3"
android:duration="500"/>
<item
android:drawable="@drawable/pic4"
android:duration="500"/>
</animation-list>
使用
Button button = (Button) findViewById(R.id.jumpto1);
button.setBackgroundResource(R.drawable.myanimation);
AnimationDrawable drawable = (AnimationDrawable) button.getBackground();
drawable.start();
使用动画注意事项:
- OOM,尤其是侦动画中图片数量以及图片过大
- 内存泄漏,属性动画中出现无限循环并且在Activity退出的时候没有及时停止
- 补间动画是对View影像做动画,有可能出现动画完成之后View无法隐藏,需要使用view.clearAnimation()进行清除。
- 兼容性问题
- 不要使用px,尽量使用dp
- 动画元素的交互
- 硬件加速