Android 3.0之前已有动画框架Animation,但存在一些局限性,当某个元素发生视图动画后,其响应事件位置还在动画前的地方。于是3.0之后,Google提出了属性动画。
ObjectAnimator
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "translationX", 300);
objectAnimator1.setInterpolator(new AccelerateInterpolator());
objectAnimator1.setDuration(2000);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);//Animation.INFINITE 表示重复多次
objectAnimator.setRepeatMode(ValueAnimator.RESTART);//RESTART表示从头开始,REVERSE表示从末尾倒播
objectAnimator1.start();
第一个参数:操纵的view 第二个参数:操纵的动画属性值 第三个参数:可变数组参数
动画属性值
translationX和translationY:增量控制view从它布局容器左上角坐标偏移
ObjectAnimator.ofFloat(imageView, "translationX", 300f);
rotation、rotationX、rotationY:控制view绕支点进行2D或3D旋转
ObjectAnimator.ofFloat(imageView, "rotation", 360); scaleX、scaleY:
控制view绕支点进行2D缩放
ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0.5f,1f);
alpha:控制view透明度,默认是1(不透明),0完全透明(不可见)
ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0.5f);
x和y:描述view在容器最终位置
可变数组参数
可以有一个到N个,如果是一个值的话默认这个值是动画过渡值的结束值。如果有N个值,动画就在这N个值之间过渡。
动画监听
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "alpha", 0.5f, 1f); objectAnimator1.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) {
}});
一般我们只关心onAnimationEnd,所以Android提供了AnimatorListenerAdapter:
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "alpha", 0.5f, 1f); objectAnimator1.addListener(new AnimatorListenerAdapter()
{
@Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation);
} });
ValueAnimator
ValueAnimator 本身不提供任何动画效果,像个数值 发生器,用来产生具有一点规律数字。
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100); valueAnimator.setTarget(imageView);
valueAnimator.setDuration(2000).start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation)
{
Int value = (Integer) animation.getAnimatedValue(); //TODO use the value Toast.makeText(getApplicationContext(), "value=" + value, Toast.LENGTH_LONG).show(); } });
PropertyValuesHolder针对同一个对象多个属性,同时作用多种动画
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("alpha", 1f, 0.5f);
PropertyValuesHolder propertyValuesHolder3 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder propertyValuesHolder4 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(imageView, propertyValuesHolder1, propertyValuesHolder2, propertyValuesHolder3, propertyValuesHolder4) .setDuration(5000).start();
AnimatorSet与PropertyValuesHolder类似,但AnimatorSet多了playTogether(同时执行)、playSequentially(顺序执行)、play(objectAnimator1).with(objectAnimator2)、before、after这些方法协同工作。
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0.5f); ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "translationY", 300); ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0, 1f); AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(5000);
animatorSet.playTogether(objectAnimator1, objectAnimator2,objectAnimator3); animatorSet.start();
xml使用属性动画
res下建立animator文件夹,然后建立res/animator/set_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="alpha"
android:valueFrom="0.1"
android:valueTo="1.0"
android:valueType="floatType" />
调用:
Animator animator = AnimatorInflater.loadAnimator(getApplicationContext(), R.animator.set_animator);
animator.setTarget(imageView);
animator.start();
动画组合 set标签,有一个orderring属性设置为together,还有另一个值:sequentially(表示一个接一个执行)。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0.5" />
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0.5" />
View的animate方法
Android 3.0后,谷歌给View增加animate方法直接驱动属性动画。
imageView.animate() .alpha(0.5f) .y(300) .setDuration(2000)
//api min is 16
.withStartAction(new Runnable() { @Override public void run() { } })
//api min is 16
.withEndAction(new Runnable() { @Override public void run() { } }).start();
布局动画
设置子View过渡动画
LinearLayout parentLayout = (LinearLayout) findViewById(R.id.parentLayout); ScaleAnimation scaleAnimation=new ScaleAnimation(0,1,0,1); scaleAnimation.setDuration(2000); LayoutAnimationController layoutAnimationController=new LayoutAnimationController(scaleAnimation,0.5f); layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL); parentLayout.setLayoutAnimation(layoutAnimationController);
通过Animator系列的API来控制动画的开始、停止和取消。
在之前的教程中,我们已经使用过多次Animator.start这个方法。这个方法是用来让动画从第一帧开始播放。该方法只是动画流控制方法集中的一个方法而已,完整的方法集合如下所示:
Animator.start() // start the animation from the beginning
Animator.end() // end the animation
Animator.cancel() // cancel the animation
Animator.pause() // added in API 19; pause the animation
Animator.resume() // added in API 19; resume a paused animation
start这个方法顾名思义是用来让动画从开头开始播放的。如果动画设置了一个大于0的播放延迟(startDelay),那么调用该方法后还需要等到延迟的时间过去才回开始播放。 我们有两种停止动画的方法,你可以用end方法抑或cancel方法来停止一个播放着的动画。在两种方式中动画都会终止并且只有再次调用start方法才会重新开始播放。两者的区别则在于停止后动画所在的状态,当你使用cancel方法来停止动画后,动画只是停止了它的时间轴,动画的状态会停在一个中间态(intermediate state)。如果通过end 方法来停止一个动画,那么动画会直接快进到该动画最后一帧并且停止,所有的对象都会保持在动画最终结束后的状态。 在 Kitkat 中增加的没有怎么被大家关注到的新API则是带来了动画可以暂停和恢复的能力。在那之前,一个动画如果被取消并且停留在当前的中间态,此时你用start方法去重启动画,动画只会从一开始重新播放。现在,你则可以调用pause方法来暂停当前播放中的动画,pause也会有和cancel方法一样的功效让动画停留在中间态,但是当你使用resume 方法去恢复这个动画的时候,动画会从这个状态继续播放下去。