一.补间动画
包括alpha(透明度)、scale(伸缩)、translate(移动)、rotate(旋转)四种,动画的xml资源文件
alpha和scale统称为Tween(渐变动画),translate和rotate统称为Frame(画面转变动画)
一般都在res/anim目录下,访问时以R.anim.XXX.xml的方式
这四种动画都继承自Animation类,它们也继承了它的公有属性:
android:duration 持续时长
android:fillAfter 为true,则保持动画结束时的状态
android:fillBefore 为true,则恢复动画开始时的状态
android:fillEnable 和fillBefore一样
android:repeatCount 重复次数
android:repeatMode 重复类型,只有reverse和restart两个值,reverse是倒序回放,restart是重放,这个属性必须和repeatCount一起使用才有效
android:interpolator 设置插值器
eg:android:interpolator="@android:anim/accelerate_decelerate_interpolator"//android自带有插值器
1.scale伸缩
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50" //缩放起点的X坐标
android:pivotY="50" //缩放起点的Y坐标
android:duration="700" />
另外关于pivot的取值:
pivotX="50%" pivotY="50%"时表示在当前控件的中心处开启缩放
pivotX="50%p" pivotY="50%p"时表示在当前控件的父控件的中心处开启缩放
2.alpha透明度
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="3000"
android:fillBefore="true" />
3.rotate旋转
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="-650"
android:pivotX="50%"
android:pivotY="50%"
android:duration="3000"
android:fillAfter="true" />
4.translate平移
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="-80"
android:fromYDelta="0"
android:toYDelta="-80"
android:duration="2000"
android:fillBefore="true" />
5.四种动画可以各自单独使用,也可以组合使用:set标签
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering=["together" | "sequentially"]>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
<scale
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"/>
<rotate
android:fromDegrees="0"
android:toDegrees="720"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
6.开启动画
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.XXX);
控件对象.startAnimation(animation)
7.关于插值器
android自带的几种插值器对一般的需求来说就已经够用了,而且自定义一个插值器对数学要求贼高:
LinearInterpolator 匀速
AccelerateDecelerateInterpolator 先加速再减速
AccelerateInterpolator 持续加速,瞬间停止
DecelerateInterpolator 持续减速,动画结束速度减为0
AnticipateInterpolator 先回拉再进行正常的动画轨迹,比如动画是要控件匀速变大,使用这个插值器会使控件先变小再正常匀速变大,类似于一个蓄力的感觉
OvershootInterpolator 它和上面一个插值器正好相反,比如控件匀速变大到指定大小,使用这个插值器就会使控件在变大到指定大小后继续变大一点,然后再弹回指定大小
AnticipateOvershootInterpolator 它是上面两个插值器的结合体,不多说了
BounceInterpolator 在目标值出弹跳,类似于乒乓球落地后来回起落的效果
CycleInterpolator 它是一个正余弦曲线,但是他和AnticipateOvershootInterpolator的区别是:它可以自定义曲线的周期,所以动画可以不到终点就结束,
也可以到达终点后回弹,回弹的次数由曲线的周期决定,曲线的周期由 CycleInterpolator() 构造方法的参数决定
二.属性动画(Android补间动画click事件还在原位怎么解决:就用属性动画)
其实Android的动画可分为ViewAnimation和PropertyAnimation两类,视图动画包括了帧动画和补间动画,属性动画包括了ValueAnimation和ObjectAnimation
1.ValueAnimator
简单使用:
private void doAnimation(){
ValueAnimator animator = ValueAnimator.ofInt(0,400);//根据实际情况也可以用ofFloat
animator.setDuration(1000);
animator.setRepeatCount(3);//设置动画重复次数,设置为ValueAnimation.INFINITE表示无限循环
animator.setRepeatMode(ValueAnimation.RESTART);//设置重复模式,restart表示正序重头开始,取值为ValueAnimation.REVERSE表示倒序重新开始
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(curValue,curValue,curValue+tv.getWidth(),curValue+tv.getHeight());
}
});
animator.setInterpolator(new BounceInterpolator());//设置插值器
animator.start();
}
tv就是一个普通的TextView对象,整个动画就是在1s内让tv从(0,0)移至(400,400)
关于插值器在第五点说补间动画时列举了系统提供这样一堆插值器对象,基本上可以满足我们的需求,
如果说一定要自定义自己的插值器的话,要去实现TimeInterpolator接口:
public class MyInterploator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
return 1-input;//input表示动画进度值,取值0~1
}
}
再来看估值器Evaluator,它是根据当前进度值来获取动画具体要改变的属性值。比如上述代码中进度如果为0.4的话那么tv的位置就是(160,160),但是上述代码中我们没有去调用animator.setEvaluator方法去设置估值器,因为它有默认的估值器:当调用的是OfInt方法时就会默认取IntEvaluator即animator.setEvaluator(new IntEvalutor()),同样的调用ofFloat方法时会默认取FloatEvaluator这俩估值器的默认公式都是:当前实际值 = 起始值+(终值-起始值)*进度值
这是IntEvaluator的源码:
public class IntEvaluator implements TypeEvaluator<Integer> {
@override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
当然我们也可以去自定义估值器,但是自定义估值器更多是在调用ofObject方法时来自定义估值器,ofInt和ofFloat只能传入整型和浮点型的参数,ofObject方法就为我们提供传入其它类型参数的方式
ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));
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();
这个动画的效果就是在十秒内加速的在tv中从A显示到Z,具体的字符切换在估值器CharEvaluator中实现:
public class CharEvaluator implements TypeEvaluator<Character> {
@Override
public Character evaluate(float fraction, Character startValue, Character endValue) {
int startInt = (int)startValue;//将字符转为ASCII码,A是65
int endInt = (int)endValue;
int curInt = (int)(startInt + fraction *(endInt - startInt));
char result = (char)curInt;
return result;
}
}
2.ObjectAnimator
上面说的ValueAnimator有个缺点就是它只能对数值进行动画设置,如果我们想对某个控件的某个属性进行动画设置还需要在addUpdateListener监听对象中用类似于tv.setText("...")这样的方式来设置属性值。ObjectAnimator就为我们提供了直接操作控件属性动画的方式,而且它派生自ValueAnimator,所以ValueAnimator中的方法在ObjectAnimator中都可以正常使用
简单用法:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "alpha", 1, 0.2, 1);
animator.setDuration(2000);
animator.start();
2s内tv(TextView对象)的透明度从1降至0.2再恢复至1,"alpha"这个参数对应的是tv的setAlpha方法,判定当前控件对象是否有该属性的依据就是该控件对象是否有该属性的set方法(驼峰式命名),ofInt和ofFloat方法用法一样,ofObject方法就加一个估值器参数即可:
ObjectAnimator animator = ObjectAnimator.ofObject(tv, "text", new CharEvaluator(), new Character('A'), new Character('Z'));
3.ValueAnimator和ObjectAnimator除了通过ofInt(),ofFloat(),ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例
直接看使用实例:
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("text", new CharEvaluator(), new Character('A'), new Character('Z'));
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(tv, rotationHolder, colorHolder, charHolder);
animator.setDuration(3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
从代码可以看出ofPropertyValuesHolder更多是对同一个控件上的动画的组合时调用,直接用PropertyValuesHolder的ofInt、ofFloat、ofObject方法来创建单个动画实例,注意这里的控件对象和控件属性是分开的 PropertyValuesHolder还提供了ofKeyframe方法来替代估值器和插值器的作用
4.不同控件动画的组合:AnimatorSet
使用示例:
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
tv1TranslateY.setStartDelay(2000);
tv1TranslateY.setRepeatCount(ValueAnimator.INFINITE);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
tv2TranslateY.setStartDelay(2000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(tv1BgAnimator,tv1TranslateY,tv2TranslateY);
animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY);//按顺序执行
animatorSet.setDuration(2000);
animatorSet.start();