Android动画-Property Animation
Posted jia-huan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android动画-Property Animation相关的知识,希望对你有一定的参考价值。
本章内容
在之前 《android动画-概述》中,我大概说了下Android Property Animation的由来,这里就不做多介绍了,Property Animation 肯定不是一章就能讲的完的,接下来的几章都是建立在代码、效果图的基础上,介绍Property Animation的用法。
本章主要讲的是 ObjectAnimator ,包括代码生成动画,XML加载动画。
简述:在给出一大堆代码之前,先通过效果图来看看一些有趣的动画,通过一个简单有趣的动画逐步展开:
这绝对是一个非常有趣的动画,包含了 alpha、translationX、translationY、rotationX、rotationY、scaleX、scaleY , 一堆 Animation 名词,在详细看这个效果的代码之前,先了解一些重要的东西,有个印象就行,毕竟之后会很详细的说明,担心后面大家看的一头雾水:
View Animation 和 Property Animation
alpha 依然不变
translate 分成了 translationX 和 translationY, 要想X轴、Y轴两个一起变化就需要将 translationX 和 translationY 组合使用
rotate 分成了 rotation、rotationX、 rotationY,其中 rotation 和 rotate基本一致,都是围绕某一个中心旋转,而 rotationX 和 rotationY 则应该算 Property Animation 带来的新的效果,这两种动画分别表示着 X轴的立体动画和Y轴的立体动画。
scale 则分成了 scaleX 和 scaleY,和 translationX/Y 一样,要想X轴、Y轴都有变化就必须一起使用
共同点:
duration 动画时间
repeatCount 动画重复次数
repeatMode 动画重复模式
Interpolator 插值器
接下来,还需要看看3.0之后,View的变化
aplha:透明度,1是完全不透明,0是完全透明,这个也没什么好说的。
setTranslationX(floatX)、setTranslationY(floatY) 这两个API的作用是对控件的位置进行调整,floatX 和 floatY 是一个相对值,相对于控件左上角原点的一个位移值。
setRotationX(floatX) 和 setRotationY(floatY) ,这两个API分别代表着 改变与X轴平面的角度、改变与Y轴平面的角度,这话说的非常抽象,事实上这两个API的效果也非常抽象,举个栗子:把X轴、Y轴看成两个垂直的平面,现在有一个ImageView 在画面上,这个ImageView 现在肯定是与Y轴的平面平行,与X轴的平面垂直,如果我设置了 setRotationX(45),这个45代表的就是一个正45度角,那么这个ImageView 就会变成一个底部向屏幕内延伸,倾斜的角度与X轴平面的角度成45度角,小角对着你。(感觉说完还是很抽象,下面会有效果,一会儿大家看看吧,事实上开发中,我基本没有用到过,好奇葩的API)
setScaleX(floatX) 、setScaleY(floatY) 这个就简单了,代表着 X轴方向的缩放,Y轴方向的缩放
setPivotX(floatX) 和 setPivotY(floatY):旋转的轴点和缩放的基准点,默认是View的中心点。和View Animation 不一样,Property Animation 提供的API和XML这两种创建动画的途径中,都没有额外的位置设置中心点,所以不管是 代码还是加载XML ,最后的中心点都是动画控件本身在代码里面去设置的。
setX(floatX) set(floatY) : 这个API是设置控件在屏幕上的绝对位置,这里 floatX 和 floatY都是 绝对坐标点
看完新的API,先贴一下上面那个 Set 动画的代码,仅仅只是看上去,很多代码,其实就是一个方法:
public void set1(View view) {
AnimatorSet set = new AnimatorSet();
set.setDuration(3000);
set.playTogether(
ObjectAnimator.ofFloat(imageView, "alpha", 0.3f, 1f),
ObjectAnimator.ofFloat(imageView, "scaleY", 0.1f, 1f),
ObjectAnimator.ofFloat(imageView, "scaleX", 0.1f, 1f),
ObjectAnimator.ofFloat(imageView, "rotationX", 0f, 360f),
ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f),
ObjectAnimator.ofFloat(imageView, "translationY", 0f, -400f, 0f),
ObjectAnimator.ofFloat(imageView, "translationX", 0f, -400f, 0f));
set.start();
}
AnimatorSet 作为 Property Animation 中的动画集合,提供了多种动画API,这里用了
public void playTogether(Animator... items)
从方法名就可以看出这是一个一起动画的API,参数是可变数组,类型是 Animator,这是一个抽象类,所以我们要使用它的子类,ObjectAnimator的父类是ValueAnimator(Property Animation核心类,本章先不介绍它),ValueAnimator继承于Animator,在 Property Animation 中做一些简单的动画,我一般都是用ObjectAnimator。
普通动画APIpublic static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
,tartget 毫无疑问是动画控件,propertyName从上面的代码中可以看出,这个给定了你要制定的动画类型,最后一个参数是一个可变数组。这里就可以看出Property Animation对于普通动画,它需要的只是结果,也即是也想要这个动画经历什么值,直接告诉API,然后其中实现、过渡这些都是不需要管的。
Alpha
这个是用代码实现的:
public void alpha(View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "alpha", 1f,
0.1f, 1f, 0.5f, 1f);
anim.setDuration(5000);
anim.start();
}
这是一个最基本的透明渐变的动画,我希望我的ImageView在5秒内的透明度 1f-0.1f-1f-0.5f-1f,然后接下来就和我没有关系了。
接下来,让我们来XML定义一个动画,xml 定义路径:res/animator
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator
android:duration="1400"
android:propertyName="alpha"
android:valueFrom="0.3"
android:valueTo="1"
android:valueType="floatType" />
<objectAnimator
android:duration="2000"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0.1"
android:valueType="floatType" />
<objectAnimator
android:duration="1400"
android:propertyName="alpha"
android:valueFrom="0.1"
android:valueTo="0.8"
android:valueType="floatType" />
</set>
很明显一个objectAnimator节点是无法承载多个动画的,必须使用set,在set下还需要指明它的子节点动画是一起执行,还是按照XML顺序依次执行。这里android:ordering="sequentially"
我规定是按照顺序依次执行。还有一个值,规定一起执行的:android:ordering="together"
。
XML中 定义:第一,执行动画的类型 android:propertyName,和 View Animation不一样,View Animation 中一种动画会有对应的节点,而Property Animation中所有基本动画的节点都是objectAnimator,区别动画的类型则是一个属性:android:propertyName。比如 alpha :android:propertyName=”alpha”。第二,在Property Animation的XML中只有android:valueFrom=”0.1” 和 android:valueTo=”0.8” 这两个动画值得存在,不存在规定 scale动画基点的属性,以及规定 rotation 中心的属性,这些都得去到java中调用对应控件的API去设置才成:setPivotX(floatX) 和 setPivotY(floatY)。
动态加载XML:
public void alpha(View view) {
// Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_alpha_animator); // 简单的透明动画
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_set_alpha); // 复杂的透明动画
animator.setTarget(imageView);
animator.start();
}
这里AnimatorInflater,就是一个用于动态加载的类。
scale
代码动画:
public void scale(View view) {
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.1f, 1f, 0.3f, 0.7f, 0.5f);
imageView.setScaleY(2);
// imageView.setScaleX(2);
anim.setDuration(3000);
anim.setRepeatCount(1);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.start();
}
这里设置了repeatCount和repaeatMode给大家看看效果,顺便测试了了一个View.setScaleY,效果很明显 动画顺序反着又播了一遍,并且控件高度变成2倍。
XML
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:ordering="together">
<set android:ordering="sequentially">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="1.5"
android:valueType="floatType" />
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1.5"
android:valueTo="0.1"
android:valueType="floatType" />
</set>
<set android:ordering="sequentially">
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0.1"
android:valueType="floatType" />
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="0.1"
android:valueTo="1.5"
android:valueType="floatType" />
</set>
</set>
正如之前说的,在Property Animation中如果想要X轴、Y轴一起变化,就需要同时使用scaleX、scaleY,在这个XML中我得想法是 把X轴的变化作为一个set,Y轴的变化是另一个set,它们的运行规定是依次运行,之后再把这两个set一起运行。也就是 together下包含着两个sequentially。其实另一种写法可以是sequentially包含着两个together,就是把某一阶段X/Y轴的变化看成是一体的,然后一阶段一阶段的进行。
rotation
先看个最简单的平面动画
public void rotate(View view) {
// ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f); 这是个逗逼的动画
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 720f);
// imageView.setRotationX(-45);
// imageView.setRotationY(-30);
imageView.setPivotX(-100f);
imageView.setPivotY(-100f);
anim.setDuration(5000);
anim.setInterpolator(new AccelerateInterpolator());
anim.start();
}
这是一个非常简单的动画,其实就是在模拟View Animation 中的rotate,这里如果不设置imageView.setPivotX(-100f); imageView.setPivotY(-100f);
那么它的默认旋转中心就是ImageView本身的中心点,需要说的是,这里的imageView.setPivotX(-100f);
imageView.setPivotY(-100f)都是相对于控件左上角的相对位置;并且这里使用了 加速 的插值器。
3D动画
public void rotate(View view) {
// ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f); 这是个逗逼的动画
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 720f);
// imageView.setRotationX(-45);
// imageView.setRotationY(-30);
imageView.setPivotX(-100f);
imageView.setPivotY(-100f);
anim.setDuration(5000);
anim.setInterpolator(new AccelerateInterpolator());
anim.start();
}
rotationY就是围绕中心点做的Y轴方向的3D动画,如果你想看X轴方向,换成rotationX就OK了。
倾斜旋转动画
public void rotate(View view) {
// ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotationY", 0f, 360f, 200f, 315f, 225f, 269f); 这是个逗逼的动画
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 720f);
imageView.setRotationX(-45);
// imageView.setRotationY(-30);
// imageView.setPivotX(-100f);
// imageView.setPivotY(-100f);
anim.setDuration(5000);
anim.setInterpolator(new AccelerateInterpolator());
anim.start();
}
imageView.setRotationX(-45) 这个API表示着,ImageView底部向屏幕内侧倾斜45°,也就是ImageVIew和X轴平面的相交,角度从90°,变成45°,就变成上图中的效果。
XML
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator
android:duration="1500"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="28"
android:valueType="floatType" />
<objectAnimator
android:duration="1500"
android:propertyName="rotationX"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
</set>
public void rotate(View view) {
// Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_rotation_animator); //简单的旋转动画
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.base_set_rotate);
animator.setTarget(imageView);
imageView.setPivotX(imageView_height);
imageView.setPivotY(0);
animator.start();
}
这个旋转动画是先正方向旋转28°,将对角线与X轴平行,然后在代码里面将对角线上的点作为中心点旋转,其实也就是绕着对角线旋转
translation
public void translate(View view) {
imageView.setTranslationX(-200);
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "translationY", 0f, -400f, 0f);
anim.setDuration(3000);
anim.start();
}
以控件左上角为原点位移-200px imageView.setTranslationX(-200)
,然后translationY,从0位移-400,最后在回到Y轴的原点。
XML
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:ordering="together">
<set android:ordering="sequentially">
<objectAnimator
android:propertyName="translationX"
android:valueFrom="-150"
android:valueTo="0" />
</set>
<set android:ordering="sequentially">
<objectAnimator
android:propertyName="translationY"
android:valueFrom="-200"
android:valueTo="0" />
<objectAnimator
android:interpolator="@android:anim/bounce_interpolator"
android:propertyName="translationY"
android:valueFrom="0"
android:valueTo="100" />
</set>
</set>
回弹的效果看不到也是没辙。
抛物线
private float setX = 0;
public void setXY(View view) {
imageView.setScaleX(0.1f);
imageView.setScaleY(0.1f);
setX = 0;
ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "cjh", 0f, 1f);
anim.setDuration(3000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();//得到动画变化的属性值
setX = 400 * value;
float setY = -1 / 75 * setX * setX + 4 * setX;
imageView.setX(setX);
imageView.setY(setY);
}
});
anim.start();
}
事实上,Property Animation 是可以拿到时间值然后自定义动画效果,代码中,我定义我要从 0 - 1,但是具体做什么我随便写的,然后在刷新监听里面,调用了抛物线的公式,然后 setX setY,不断更新ImageView的位置
至此,关于 Proerty Animation 的基本使用都讲完了,主要是详细的讲了 ObjectAnimator 的使用和XML的写法,接下来就是更为重要的动画了。
源码下载
以上是关于Android动画-Property Animation的主要内容,如果未能解决你的问题,请参考以下文章
Android 属性动画(Property Animation) 完全解析 (上)