Android 属性动画
Android 属性动画
前言
有人告诉我,记下来比较好,总是百度不是办法,对吧,好记性,不如懒键盘?Take is cheap , show me the code ! 真经典。
1、View
所有看得见的东西,布局、控件什么的都和View有关,就是这么个东西。
2、ValueAnimator 核心类
原理:不断改变值,从现有值到给定值靠拢。(就是根据给定的动画时间一直+±-的,所以动画时间是必须给定的值)有三个重要方法。
2.1 ValueAnimator.ofInt(int values)
以整数形式过渡
ValueAnimator valueAnimator = null;
valueAnimator = ValueAnimator.ofInt(0,800);//初始的值和结束的值
valueAnimator.setDuration(2000);//动画运行时间
valueAnimator.setStartDelay(200);//延迟的时间
valueAnimator.setRepeatCount(0);//-1 无限循环 0 不循环
valueAnimator.setRepeatMode(ValueAnimator.RESTART);//重放模式 三个参 1 2 对应三个模式
// ValueAnimator.RESTART(默认):正序重放
// ValueAnimator.REVERSE:倒序回放
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
btn.getLayoutParams().width = (int) animation.getAnimatedValue(); //变换按钮的长~~
btn.requestLayout();//重新绘制按钮~~
}
});
valueAnimator.start();
ofInt可以带许多参数,让过渡更平滑自然
valueAnimator = ValueAnimator.ofInt(0,100,200,300,400,500,600,700,800);//初始的值和结束的值
2.1.1 什么是估值器(TypeEvaluator)
插值器(Interpolator)决定 值 的变化模式(匀速、加速blabla)
估值器(TypeEvaluator)决定 值 的具体变化数值
ofInt() 和 oFloat() 都有自带的估值器,ofObject()过于复杂需要自定义估值器。
2.2 ValueAnimator.oFloat(float values)
和上面那个一样,不过是以浮点类型数过渡
2.3 ValueAnimator.ofObject()
就是创建两个对象,一个是初始的对象,一个是动画后的对象。慢慢的将初始对象的属性变化为第二个对象的属性,因为涉及的属性等不明,复杂。所以需要自定义估值器。
2.3.1 自定义一个估值器
public class ViewTypeEvaluator implements TypeEvaluator {
//重写evaluate方法
/**
* @param fraction 表示动画完成度(根据它来计算当前动画的值)
* @param startValue 动画的初始值 Object 类型
* @param endValue 动画的结束值 Object 类型
* @return
*/
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
//动画逻辑 这就看想做什么动画了
AnimObject startAnimObject = (AnimObject)startValue;//强转成我们自己的对象
AnimObject endAnimObject = (AnimObject)endValue;//强转成我们自己的结束对象
// 根据fraction来计算当前动画的x和y的值
float x = startAnimObject.getX() + fraction * (endAnimObject.getX() - startAnimObject.getX());
float y = endAnimObject.getY() + fraction * (endAnimObject.getY() - startAnimObject.getY());
int width =endAnimObject.getWidth() - startAnimObject.getWidth() ;
int height =endAnimObject.getHeight() - startAnimObject.getHeight() ;
// 将计算后 所有属性 封装回对象中
AnimObject object = new AnimObject(x,y,width,height);
return object;
}
}
2.3.2 具体实现
因为是两个对象所以需要一个对象类来存储对象的属性。
public class AnimObject {
private float x,y;//坐标
private int width,height;//宽高
// 构造方法用于设置坐标
public AnimObject(float x, float y) {
this.x = x;
this.y = y;
}
// 构造方法用于设置宽高
public AnimObject(int width, int height) {
this.width = width;
this.height = height;
}
// 构造方法用于设置坐标和宽高
public AnimObject(float x, float y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public void setY(float y) {
this.y = y;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
使用
AnimObject startObject = new AnimObject(btn.getX(),btn.getY(),btn.getLayoutParams().width,btn.getLayoutParams().height);
AnimObject endObject = new AnimObject(700, 1000,100,500);
ValueAnimator valueAnimator = ValueAnimator.ofObject(new ViewTypeEvaluator(),startObject,endObject) ;
2.4 ObjectAnimator类(继承了ValueAnimator类,一般用这个)
2.5 组合动画(AnimatorSet 类)
AnimatorSet.play(Animator anim) :播放当前动画
AnimatorSet.after(long delay) :将现有动画延迟x毫秒后执行
AnimatorSet.with(Animator anim) :将现有动画和传入的动画同时执行
AnimatorSet.after(Animator anim) :将现有动画插入到传入的动画之后执行
AnimatorSet.before(Animator anim) : 将现有动画插入到传入的动画之前执行
// 步骤1:设置需要组合的动画效果
ObjectAnimator translation = ObjectAnimator.ofFloat(mButton, "translationX", curTranslationX, 300,curTranslationX);
// 平移动画
ObjectAnimator rotate = ObjectAnimator.ofFloat(mButton, "rotation", 0f, 360f);
// 旋转动画
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton, "alpha", 1f, 0f, 1f);
// 透明度动画
// 步骤2:创建组合动画的对象
AnimatorSet animSet = new AnimatorSet();
// 步骤3:根据需求组合动画
animSet.play(translation).with(rotate).before(alpha);
animSet.setDuration(5000);
// 步骤4:启动动画
animSet.start();
2.6 ViewPropertyAnimator用法
// 使用解析
View.animate().xxx().xxx();
// ViewPropertyAnimator的功能建立在animate()上
// 调用animate()方法返回值是一个ViewPropertyAnimator对象,之后的调用的所有方法都是通过该实例完成
// 调用该实例的各种方法来实现动画效果
// ViewPropertyAnimator所有接口方法都使用连缀语法来设计,每个方法的返回值都是它自身的实例
// 因此调用完一个方法后可直接连缀调用另一方法,即可通过一行代码就完成所有动画效果
// 以下是例子
mButton = (Button) findViewById(R.id.Button);
// 创建动画作用对象:此处以Button为例
mButton.animate().alpha(0f);
// 单个动画设置:将按钮变成透明状态
mButton.animate().alpha(0f).setDuration(5000).setInterpolator(new BounceInterpolator());
// 单个动画效果设置 & 参数设置
mButton.animate().alpha(0f).x(500).y(500);
// 组合动画:将按钮变成透明状态再移动到(500,500)处
// 特别注意:
// 动画自动启动,无需调用start()方法.因为新的接口中使用了隐式启动动画的功能,只要我们将动画定义完成后,动画就会自动启动
// 该机制对于组合动画也同样有效,只要不断地连缀新的方法,那么动画就不会立刻执行,等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动
// 如果不想使用这一默认机制,也可以显式地调用start()方法来启动动画
2.7 监听动画
Animation.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始时执行
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复时执行
}
@Override
public void onAnimationCancel()(Animation animation) {
//动画取消时执行
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束时执行
}
});
// 特别注意:每次监听必须4个方法都重写。
AnimatorListenerAdapter 动画适配器
anim.addListener(new AnimatorListenerAdapter() {
// 向addListener()方法中传入适配器对象AnimatorListenerAdapter()
// 由于AnimatorListenerAdapter中已经实现好每个接口
// 所以这里不实现全部方法也不会报错
@Override
public void onAnimationStart(Animator animation) {
// 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
}
});