效果图:
属性动画(Property Animation):这个是在Android 3.0中才引进的,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的 有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
为什么使用属性动画(Property Animation)?
因为它可以改变对象的属性,能产生更强大的动画。
Property Animation相关类:
1.ValueAnimator:包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等
2.ObjectAnimator :继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性
但用ObjectAnimator有一 定的限制,要想使用ObjectAnimator,应该满足以下条件:
对象应该有一个setter函数:set(驼峰命名法),就是该对象必须要有属性,并能为其设置values。
为了获得当前值,该对象要有相应属性的getter方 法:get,如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。
3.AnimatorSet :提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
4.AnimatorInflater :用与加载属性动画的xml文件
5.TypeEvalutors: 类型估值,主要用于设置动画操作属性的值
android提供了以下几个evalutor:
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为十六进制颜色值;
6.TimeInterplator:time interplator定义了属性值变化的方式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了 TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
android提供了以下Interplator:
AccelerateInterpolator 开始时慢中间加速
DecelerateInterpolator 开始时快然后减速
AccelerateDecelerateInterolator 开始结束时慢,中间加速
AnticipateInterpolator 先向相反方向改变一段再加速播放
AnticipateOvershootInterpolator 反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator 线性均匀改变
OvershottInterpolator 超越,最后超出目的值然后缓慢改变到目的值
相关属性:
1.Duration动画的持续时间,默认300ms。
2.Time interpolation:插值,就是Tween动画中的Interpolation
4.Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
5.Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。
6.Frame refresh delay:帧刷新延迟,对于你的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态;基本不用管
最后给出源码:
activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:src="@drawable/seven" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="改变整个布局的颜色"
android:onClick="btn_ll"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="ObjectAnimator"
android:onClick="btn_object"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="ValueAnimator"
android:onClick="btn_value"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="AnimatorSet"
android:onClick="btn_set"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="自定义View"
android:onClick="btn_custom"/>
</LinearLayout>
</LinearLayout>
动画xml:
res/animator/object_animator
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="backgroundColor"
android:repeatCount="infinite"
android:repeatMode="restart"
android:valueFrom="#ff0000"
android:valueTo="#0000ff"
android:valueType="intType" >
<!-- android:propertyName 设置属性动画名称 -->
<!-- android:repeatCount="infinite" 设置循环次数为循环 -->
<!-- android:interpolator 设置动画的播放速度 -->
<!-- android:repeatMode="restart" 设置替换模式,默认为顺序播放 reverse 倒序播放 -->
<!-- android:valueFrom 设置播放动画的起始的状态 -->
<!-- android:valueTo 设置播放动画的结束状态 -->
<!-- android:valueType 设置播放的类型 -->
</objectAnimator>
res/animator/object_rotate
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="rotation"
android:interpolator="@android:anim/cycle_interpolator"
android:duration="5000"
android:repeatCount="infinite"
android:valueFrom="0.0"
android:valueTo="720"
android:valueType="floatType"
android:repeatMode="reverse">
</objectAnimator>
自定义View动画类
import android.animation.AnimatorInflater;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.view.View;
public class MyAnimator extends View {
public MyAnimator(Context context) {
super(context);
ObjectAnimator oAnimator = (ObjectAnimator) AnimatorInflater
.loadAnimator(context, R.animator.object_animator);
// 设置动画计算器,解析当前的颜色ARGB
oAnimator.setEvaluator(new ArgbEvaluator());
// 设置将当前动画加载至对应的控件上
oAnimator.setTarget(this);
// 播放动画
oAnimator.start();
}
}
MainActivity:
import android.os.Bundle;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
private float windowHeight;
private float windowWidth;
private LinearLayout ll_linearLayout;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.iv_image);
// 获取屏幕测量工具类
DisplayMetrics oDisplayMetrics = new DisplayMetrics();
// 根据通过管理者获得屏幕显示的高度 Metrics 度量
getWindowManager().getDefaultDisplay().getMetrics(oDisplayMetrics);
windowHeight = oDisplayMetrics.heightPixels;
windowWidth = oDisplayMetrics.widthPixels;
}
public void btn_ll(View view){
ll_linearLayout = (LinearLayout) findViewById(R.id.ll_linear);
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater
.loadAnimator(this, R.animator.object_animator);
//Evaluator 请求
animator.setEvaluator(new ArgbEvaluator());
//target表示当前动画所承载的控件
animator.setTarget(ll_linearLayout);
//动画开始
animator.start();
}
public void btn_object(View view){
objectAnimator_java();
//objectAnimator_xml();
}
/**
* 使用Java代码实现属性动画
* */
private void objectAnimator_java() {
// float...values 这个是可变的数组类型
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,
"rotationY", 0.0f, 360.0f);
animator.setDuration(5000);
animator.setInterpolator(new LinearInterpolator());
// 循环次数
animator.setRepeatCount(2);
// 循环模式
animator.setRepeatMode(0);
// 播放动画
animator.start();
}
private void objectAnimator_xml() {
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater
.loadAnimator(this, R.animator.object_rotate);
animator.setTarget(this);
animator.start();
}
public void btn_value(View view){
valueAnimator_Y_java();
// valueAnimator_X_java();
}
/*
* 自由落体动画
*/
private void valueAnimator_Y_java() {
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, windowHeight
- imageView.getHeight());
animator.setDuration(5000);
animator.setTarget(imageView);
animator.start();
// 动画改变监听器
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
imageView.setTranslationY((Float) animation.getAnimatedValue());
}
});
}
/**
* 水平运动
*/
private void valueAnimator_X_java() {
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, windowWidth
- imageView.getWidth());
animator.setDuration(5000);
animator.setTarget(imageView);
animator.start();
// 动画改变监听器
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
imageView.setTranslationX((Float) animation.getAnimatedValue());
}
});
}
public void btn_set(View view){
animator_set();
// animator_set_order();
}
private void animator_set() {
// target表示当前动画所承载的控件
// propertyName当前所实现的什么动画
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,
"rotationX", 0.0f, 360.0f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView, "scaleY",
1.0f, 2.0f);
AnimatorSet oSet = new AnimatorSet();
oSet.playTogether(animator, animator2);
oSet.setDuration(5000);
oSet.start();
}
private void animator_set_order() {
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,
"rotationX", 0.0f, 360.0f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView, "scaleY",
1.0f, 2.0f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageView,
"rotationY", 0.0f, 360.0f);
ObjectAnimator animator4 = ObjectAnimator.ofFloat(imageView, "scaleX",
1.0f, 2.0f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(animator3).with(animator).after(animator4)
.after(animator2);
animatorSet.setDuration(7000);
animatorSet.start();
}
public void btn_custom(View view){
//实例化自定义View
MyAnimator myAnimator=new MyAnimator(this);
//设置控件的高宽
LinearLayout.LayoutParams params=new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
//设置控件的间距
params.setMargins(5, 5, 5, 5);
//将设置的布局参数加至view
view.setLayoutParams(params);
//将自定义控件添加至线性布局
ll_linearLayout.addView(myAnimator);
}
}
属性动画到此结束,还不会的小伙伴赶快敲起来吧。