上一篇总结了View动画相关的知识,这一节主要学习Android种的属性动画–也是当前最经常使用的一种动画。它能实现View动画所不能实现的一些动画效果。
1.简介
属性动画(Property Animation
)是在 Android 3.0(API 11)后才提供的一种全新动画模式,它大大解决传统动画的局限性,如:经过动画后,其点击事件的响应区域依然未改变。它具有相当高的灵活性,我们可以通过反射机制动态的设置某一个类种的属性从而达到动画的效果。
作用对象:任意Java
对象
具体逻辑:此图引用自感谢作者
其继承结构:
而我们平常主要使用的是ValueAnimator
与ObjectAnimator
,下面主要介绍它的使用。
2.TypeEvaluator-估值器
如果想要自定义复杂的动画效果,那么我们必须要了解TypeEvaluator。什么是TypeEvaluator呢?
简单来说,就是告诉动画系统如何从初始值过度到结束值。ValueAnimator
内部自带FloatEvaluator
。我们通过源码可以发现其实现了·TypeEvaluator
接口,并且重写了evaluate方法
。
/**
* This evaluator can be used to perform type interpolation between <code>float</code> values.
*/
public class FloatEvaluator implements TypeEvaluator<Number> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>float</code> or
* <code>Float</code>
* @param endValue The end value; should be of type <code>float</code> or <code>Float</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
变量 | 含义 |
---|---|
fraction | 表示动画完成度 |
startValue | 表示动画开始值 |
endValue | 表示动画结束值 |
3.ValueAnimator的基本使用
看一个简单的Demo,学习基本的使用:
//ValueAnimator
//0-2-1之间在5s内重复执行2次,延时一秒开始执行
//final ValueAnimator animator = ValueAnimator.ofFloat(0f,2f,1f);
final ValueAnimator animator = ValueAnimator.ofInt(0, 2, 1);
//动画持续时长
animator.setDuration(5000);
//重复次数
animator.setRepeatCount(2);
//延迟多久后开始执行
animator.setStartDelay(1000);
//动画重复模式,RESTART代表重新播放 REVERSE代表倒序播放
animator.setRepeatMode(ValueAnimator.RESTART);
//进度更新的监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.e("wdl", "onAnimationUpdate: " + (int) animation.getAnimatedValue());
}
});
基本的方法有:
3.ObjectAnimator的基本使用
ObjectAnimator.ofXxx(Object target,String propertyName,Args...value)
,第一个参数代表目标对象,第二个参数为想要操作的属性名,最后一个为一个可变长参数。
//独立动画效果
//透明度
final ObjectAnimator alphaObjectAnimator = ObjectAnimator
.ofFloat(imageView,"alpha",1f,0f,1f);
//旋转
final ObjectAnimator rotateObjectAnimator = ObjectAnimator
.ofFloat(imageView,"rotation",0f,360f);
//缩放
final ObjectAnimator scaleXObjectAnimator = ObjectAnimator
.ofFloat(imageView,"scaleX",1f,2f,1f);
final ObjectAnimator scaleYObjectAnimator = ObjectAnimator
.ofFloat(imageView,"scaleY",1f,2f,1f);
float translateY = imageView.getTranslationY();
Log.e("wdl", "translateY: "+translateY);
final ObjectAnimator translateYObjectAnimator = ObjectAnimator.
ofFloat(imageView,"translationY",
translateY,-600f,translateY);
// alphaObjectAnimator.setDuration(5000);
// rotateObjectAnimator.setDuration(5000);
// scaleXObjectAnimator.setDuration(5000);
// scaleYObjectAnimator.setDuration(5000);
// translateYObjectAnimator.setDuration(5000);
//FloatEvaluator
//组合动画
final AnimatorSet animatorSet = new AnimatorSet();
//play方法返回一个Builder对象
//树结构
//after 就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点)
//before 在当前基础上添加孩子节点,可以添加2个子节点
animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
.after(rotateObjectAnimator)
.before(scaleXObjectAnimator).before(scaleYObjectAnimator);
animatorSet.setDuration(5000);
//添加所有的监听
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
//根据需求重写监听方法
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
}
});
其中AnimatorSet
,组合动画有四个方法:
//play方法返回一个Builder对象
//树结构
//after 就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点)
//before 在当前基础上添加孩子节点,可以添加2个子节点
animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
.after(rotateObjectAnimator)
.before(scaleXObjectAnimator).before(scaleYObjectAnimator);
animatorSet.setDuration(5000);
查看相关源码:
/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
* ends.
*
* @param anim The animation that will play when the animation supplied to the
* {@link AnimatorSet#play(Animator)} method ends.
*/
public Builder before(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addChild(node);
return this;
}
/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
* to start when the animation supplied in this method call ends.
*
* @param anim The animation whose end will cause the animation supplied to the
* {@link AnimatorSet#play(Animator)} method to play.
*/
public Builder after(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addParent(node);
return this;
}
可以看出,使用的是树结构:
方法 | 作用 |
---|---|
play | 方法返回一个Builder对象 |
with | 与play种的动画一起执行 |
after | 就是在当前的基础上添加一个父亲节点 ,只能添加一个父亲节点(子节点只能有一个父亲节点),此动画在前面的动画之前执行 |
before | 在当前基础上添加孩子节点,可以添加2个子节点,在前面的动画之后执行 |
4.总结一下常用的方法
方法 | 作用 |
---|---|
setDuration | 动画持续时长 |
setRepeatCount | 动画重复次数 |
setStartDelay | 动画延时开始的时长 |
setRepeatMode | 动画重复模式 |
addUpdateListener | 动画监听 |
5.XML中使用
动画相关文件位于res/animator/
下。
基本使用:(基本的属性作用与Java代码中的类似)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<!-- android:ordering sequentially按照xml文件中的先后顺序执行 together同时执行 -->
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" />
<set android:ordering="together">
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
<set android:ordering="sequentially">
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" />
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</set>
</set>
Java中使用:
Animator xmlAnimator = AnimatorInflater.loadAnimator(this,R.animator.animations);
//将动画设置给对应的view
xmlAnimator.setTarget(imageView);
xmlAnimator.start();
本文参考:
https://blog.csdn.net/guolin_blog/article/details/43816093
https://www.jianshu.com/p/2412d00a0ce4
https://blog.csdn.net/guolin_blog/article/details/43536355
https://blog.csdn.net/guolin_blog/article/details/43816093