Android动画全解析(持续更新)

动画

动画分类

Tween 动画、Frame 动画

帧动画(Frame 动画)

一张一张的图片按照顺序和时间进行一帧一帧的播放

思路:将图片资源作为背景图片,依次播放。用到的类:AnimationDrawable

使用XML实现

1 将资源图片导入到对应的 drawable-xxx 或drawable 目录中

2 在其目录下,创建xml文件,根节点选择 animation-list

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >	//自动执行,true,停在最后一帧(只播放一次),false,循环播放
    <item
        android:drawable="@drawable/logo1"
        android:duration="850">		//设置持续时长
    </item>
    <item
        android:drawable="@drawable/logo2"
        android:duration="850">
    </item>
</animation-list>

3 java代码

ImageView iv = (ImageView) findViewById(R.id.iv);   //找到图片控件
iv.setBackgroundResource(R.drawable.logo);		   //导入资源文件
AnimationDrawable anim = (AnimationDrawable) iv.getBackground();	
anim.start();									//开始播放动画

使用代码实现

方法一:添加多个帧 Drawable

mAnimationDrawable = new AnimationDrawable();
mAnimationDrawable.setOneShot(false);//是否执行一次
for(int i=0;i<11;i++){				//添加多个帧 Drawable
	Drawable frame = getResources().getDrawable(R.drawable.girl_1+i);
	mAnimationDrawable.addFrame(frame, 200);
}
mImageView.setImageDrawable(mAnimationDrawable);	//设置帧动画,默认是停止状态

方法二:引用xml 帧动画drawable

// 引用xml 帧动画drawable
mAnimationDrawable=(AnimationDrawable)getResources().getDrawable(R.drawable.frame);
mImageView.setImageDrawable(mAnimationDrawable);

补间动画(Tween动画)

补间动画也叫渐变动画,对特定的对象做图像变换如平移、缩放、旋转、淡出/淡入等

动画类型 XML节点 使用的java类
透明 alpha AlphaAnimation
缩放 scale ScaleAnimation
移动 translate TranslateAnimation
旋转 rotate RoateAnimation
动画集合 set AnimationSet

属性解析

缩放
fromXScale 起始X方向相对自身的缩放比例,浮点值。1.0:无变化,0.5缩小一倍
toXScale 结尾X方向相对自身的缩放比例
fromYScale 起始Y方向相对自身的缩放比例
toYScale 结尾Y方向相对自身的缩放比例
pivotX 缩放起点的X轴坐标,可以是数值,百分数,百分数p
数值:如50,当前View的左上角X轴坐标 + 50px作为动画起点
百分数:如50%,当前View的左上角X轴坐标 + 自身X轴方向宽度的50%作为动画起点
百分数p:如50%P,当前View左上角X轴坐标 + 父控件X轴方向宽度50%作为动画起点
pivotY 缩放起点的X轴坐标,同pivotX
透明
fromAlpha 动画开始时的透明度,从0.0-1.0,0.0:全透明,1.0:完全不透明
toAlpha 动画结束时的透明度
旋转
fromDegrees 开始旋转的角度位置,正直:顺时针方向度数,反之同理
toDegrees 结束时旋转到的角度位置
pivotX 同缩放
pivotY 同缩放
平移
fromXDelta 起始点的X轴坐标,具体数值同pivotX
fromYDelta 起始点的Y轴坐标
toXDelta 结束点的X轴坐标
toYDelta 结束点的Y轴坐标

通用属性

duration 动画持续时间
fillAfter 设为true,动画结束时,保持动画最后时状态
fillBefore 设置true,动画结束时,动画还原到初始化状态
fillEnabled 同fillBefore
repeatCount 重复次数
repeatMode 重复类型,reverse:倒序播放,restart:重新播放
duration 单次动画持续时间,单位毫秒

使用XML实现

在res/anim 目录下创建set.xml文件

<--!各标签中属性参照动画类的构造方法中的参数及常用方法 -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="false" >
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
   	android:fromAlpha="0.0"			
    android:toAlpha="1.0"			
    android:duration="2000"
    android:repeatCount="infinite"
    android:repeatMode="reverse" >
</alpha>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
	android:duration="2000"
	android:fromDegrees="0"
	android:pivotX="50%"
	android:pivotY="50%"
	android:repeatCount="2"
	android:repeatMode="reverse"
	android:toDegrees="360" >
    </rotate>
</set>
Animation set = AnimationUtils.loadAnimation(this, R.anim.set);	//单个动画所用方法一致
iv.startAnimation(set);

使用代码实现

常用类构造方法解析

AlphaAnimation(float fromAlpha, float toAlpha);
        //fromAlpha: 动画的起始alpha值 (范围:0:完全透明 -1:完全不透明)
        //toAlpha:终止的值,动画结束的值

TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, 
                int fromYType,float fromYValue,int toYType, float toYValue)
//fromXType(起点,相对于原点偏移方式)
	Animation.ABSOLUTE 绝对值,像素值
	Animation.RELATIVE_TO_SELF 相对于自己
	Animation.RELATIVE_TO_PARENT 相对于父控件
//fromXValue(起点,相对于原点偏移量),绝对值/百分比

ScaleAnimation(float fromX,float toX,float fromY,float toY, 
                int pivotXType,float pivotXValue,int pivotYType, float pivotYValue)
//fromX: 缩放起始比例-水平方向
//toX: 缩放最终比例-水平方向
//pivotXType(中心点相较于原点 x方向的类型): 
	Animation.ABSOLUTE
	Animation.RELATIVE_TO_SELF
	Animation.RELATIVE_TO_PARENT
//pivotXValue: 绝对值/百分比    
RotateAnimation(float fromDegrees,float toDegrees,int pivotXType,float pivotXValue, 				int pivotYType, float pivotYValue)

动画类的通用方法

setDuration(3000);	// 每次动画持续时间3秒
setFillAfter(true);	// 动画最后停留在终止的状态
setRepeatCount(3);	// 动画重复的次数
setRepeatMode(Animation.REVERSE);	// REVERSE: 反转模式 RESTART:重新开始
setInterpolator(new BounceInterpolator(2f));	// 设置特效
start();
cancle();
AnimationSet set = new AnimationSet(false);
AlphaAnimation al = new AlphaAnimation(0,1);//范围:0:完全透明,1:完全不透明
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, 
                                             Animation.RELATIVE_TO_SELF, 0.5f);

ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f,
										Animation.RELATIVE_TO_SELF, 0.5f, 												Animation.RELATIVE_TO_SELF, 0.5f);

TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0, 
											Animation.RELATIVE_TO_SELF,1f,
											Animation.RELATIVE_TO_SELF,0,
											Animation.RELATIVE_TO_SELF,1f);
set.addAnimation(al);
set.addAnimation(ra);
set.addAnimation(sa);
set.addAnimation(ta);

iv.startAnimation(set);

属性动画(Property动画)

引入原因:补间动画功能只能覆盖移动,缩放,旋转,透明四种对view的操作,局限性大。只改变view的显示效果,不改变view的属性

使用XML实现

java类 XML标签
ValueAnimator animator
ObjectAnimator objectAnimator
AnimatorSet set set标签可嵌套
//创建res/animator/objectAnimator资源
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
	android:propertyName="alpha"    
	android:duration="3000"
	android:repeatCount="3"
	android:repeatMode="reverse"
	android:valueFrom="0.0"
	android:valueTo="1.0">
</objectAnimator>
//AnimatorInflater应用
Animator animator = AnimatorInflater.loadAnimator(this,R.animator.alpha);		//加载动画资源
animator.setTarget(iv);	 //指定要显示动画的控件
animator.start();		//开启动画

使用代码实现

//translationX:围绕X轴旋转,translationX:围绕Y轴旋转,setRotation:围绕Z轴旋转,其他同理
//右,下,上为正
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha",new float[]{0.0f,0.2f,0.4f,0.6f,0.8f,1.0f});
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX",new float[] {10f,20f,40f,70f,100f});
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleX",new float[] {1f,2f,3f,4f,5f,6f});
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY",new float[] {90f,180f,270f,360f});
//动画集合
AnimatorSet set = new AnimatorSet();
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX",new float[] {10f,20f,30f,40f,60f});
ObjectAnimator ob = ObjectAnimator.ofFloat(iv, "translationY",new float[] {-10f,-20f,-30f,-40f});
set.playTogether(oa, ob);
set.setDuration(3000);
set.start();

AnimatorSet

组合动画功能实现。

play():传入一个Animator对象(ValueAnimator或ObjectAnimator ),返回一个AnimatorSet.Builder实例

AnimatorSet.Builder方法

after(Animator anim) 现有动画在传入动画后执行
after(long delay) 现有动画延迟指定毫秒后执行
before(Animator anim) 现有动画在传入动画前执行
with(Animator anim) 现有动画与传入动画同时执行
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);  
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
AnimatorSet animSet = new AnimatorSet();  
animSet.play(rotate).with(fadeInOut).after(moveIn);  
animSet.setDuration(5000);  
animSet.start(); 

ValueAnimator

属性动画的运行机制是通过不断地对值进行操作来实现的,ValueAnimator实现初始值与结束值间值运算

Android动画全解析(持续更新)

ofFloat()ofInt()ofObject() 动画范围
setStartDelay() 动画延迟播放的时间
setRepeatCount() 动画循环播放的次数
setRepeatMode() 循环播放的模式,RESTART:重播,REVERSE:倒叙播放
//ValueAnimator ofObject(TypeEvaluator evaluator, Object... values); 
ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));  //CharEvaluator内数值变化与其他类似,对应ASCII码表
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        char text = (char)animation.getAnimatedValue();  
        tv.setText(String.valueOf(text));  
    }  
});  
animator.setDuration(10000);  
animator.setInterpolator(new AccelerateInterpolator());  
animator.start();

使用ofObject(),自定义CharEvaluator实现园缩放特效:链接

ObjectAnimator

对任意对象的任意属性进行动画操作

ObjectAnimator ofFloat(Object target, String propertyName, float... values);
//参数:控件,控件属性,变化范围

动画原理

Android动画全解析(持续更新)
ValueAnimator中,我们要通过添加监听器来监听当前数字值

ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字

set函数拼写:属性首字母大小 + set/Set + 对应set函数名

ViewPropertyAnimator

提供更易懂API,实现属性动画。支持连缀用法

1 ViewPropertyAnimator功能均建立在View类新增的animate()方法之上,创建并返回一个ViewPropertyAnimator实例
2 ViewPropertyAnimator隐式启动动画,不需要调用start()。此机制对于组合动画同样有效

ObjectAnimator extends ValueAnimator
ValueAnimator  extends Animator
ViewPropertyAnimator animator = textview.animate();	//生成ViewPropertyAnimator对象
animator.alpha(0f);  		//将当前的textview变成透明状态
animator.x(500).y(500); 	 //让textview运动到500,500这个坐标点
animator.x(500).y(500).setDuration(5000);  //设定动画的运行时长
animator.x(500).y(500).setDuration(5000)  
        .setInterpolator(new BounceInterpolator());  //使用Interpolator

Animator

addListener ():任何继承自Animator 的类共有方法

Anim.addListener(new AnimatorListener() {  
    @Override  //动画开始的时候调用
    public void onAnimationStart(Animator animation) {}  

    @Override  //动画重复执行的时候调用
    public void onAnimationRepeat(Animator animation) {}  

    @Override  //动画结束的时候调用
    public void onAnimationEnd(Animator animation) {}  

    @Override  //动画被取消的时候调用
    public void onAnimationCancel(Animator animation) {}  
});  

AnimatorListenerAdapter:系统提供的适配器类,解决接口繁琐问题

Anim.addListener(new AnimatorListenerAdapter() {  //可自定义实现其中方法
    @Override  
    public void onAnimationEnd(Animator animation) {}  
}); 

Evaluator

转换器,将进度转换为对应的数值位置

Android动画全解析(持续更新)

从定义动画的数字区间到通过AnimatorUpdateListener中得到当前动画所对应数值的整个过程

ofInt(0,400):指定动画的数字区间,从0到400

插值器Interpolator:动画开始后,通过Interpolator返回当前动画的数字进度(百分制,小数表示,如0.2)

Evaluator:将从插值器Interpolator返回的数字进度转成对应的数字值:当前的值 = 100 + (400 - 100)* 显示进度

监听器:通过在AnimatorUpdateListener监听器使用animation.getAnimatedValue()函数拿到Evaluator返回值

Evaluator使用

//ofInt()对应的Evaluator类名叫IntEvaluator,其ofFloat()同理
ValueAnimator animator = ValueAnimator.ofInt(0,600);  	//调用的是ofInt()
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        int curValue = (int)animation.getAnimatedValue();  //可强转为int
    }  
});  
animator.setDuration(1000);  
animator.setEvaluator(new IntEvaluator());  	//设置系统IntEvaluator
animator.setInterpolator(new BounceInterpolator());  
animator.start();  

自定义Evalutor

系统实现TypeEvaluator接口的有:IntEvaluator,FloatEvaluator,PointEvaluator,IntArrayEvaluator,FloatArrayEvaluator,RectEvaluator,ArgbEvaluator,PointFEvaluator

//自定义MyEvaluator实现TypeEvaluator<Integer>,注意泛型
public class MyEvaluator implements TypeEvaluator<Integer> {  
    @Override  
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;  
        return (int)(200+startInt + fraction * (endValue - startInt));  
    }  
}
//实现动画
ValueAnimator animator = ValueAnimator.ofInt(0,400);  
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        int curValue = (int)animation.getAnimatedValue();  
    }  
});  
animator.setDuration(1000);  
animator.setEvaluator(new MyEvaluator());  
animator.start();  

ArgbEvalutor

颜色值过渡转换

高级进阶:https://github.com/harvic/BlogResForGitHub

ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);  //颜色范围
animator.setEvaluator(new ArgbEvaluator());  
animator.setDuration(3000);  
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        int curValue = (int)animation.getAnimatedValue();  //返回值可作为空间的背景颜色
        tv.setBackgroundColor(curValue); 
    }  
});  
animator.start();  

Interpolator

插值器,控制动画变化速率与类型。在属性动画中,颜色变化随速率变化。系统默认的Interpolator为AccelerateDecelerateInterpolator

实现类 意义
AccelerateDecelerateInterpolator 中间快,首尾慢
AccelerateInterpolator 越来越快
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 结束时弹起
CycleInterpolator 循环播放,速率沿正弦曲线改变
DecelerateInterpolator 开始快,越来越慢
LinearInterpolator 匀速
OvershootInterpolator 向前甩一定值后再回到原来位置

自定义Interpolator

//自定义DecelerateAccelerateInterpolator实现TimeInterpolator接口
//input:随着动画运行而变化,范围:0~1。动画开始时为0,结束时为1,中间在0~1间变化
public class DecelerateAccelerateInterpolator implements TimeInterpolator{  
    @Override  
    public float getInterpolation(float input) {  //先减速后加速
        float result;  
        if (input <= 0.5) {  
            result = (float) (Math.sin(Math.PI * input)) / 2;  
        } else {  
            result = (float) (2 - Math.sin(Math.PI * input)) / 2;  
        }  
        return result;  
    }  
}