属性动画之ObjectAnimator

    ObjectAnimator,通过设置改变对象的属性来实现动画效果,常用的方法有这么几种,ofFloat()、ofInt()、ofObject()、ofArgb()、ofPropertyValuesHolder(),具体含义及使用我们在下面的实例中进行讲解。

一、动画类型

    使用ObjectAnimator也是可以轻松的实现平移、缩放、旋转、透明度这几种动画效果的,与补间动画的使用效果是一样的,那就先来看看这几种常用的动画是怎么实现的。

工程代码里就是一个ImageView控件和Activity,

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<ImageView
    android:id="@+id/head"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:src="@drawable/head" />

</RelativeLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_object_animator);
        head = (ImageView) findViewById(R.id.head);
    }
    我们这里就是对ImageView控件head实现动画效果,本质就是改变head的属性。


1.平移(translate)
// 平移
private void translateAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0.0f);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}
    这段代码就是用来实现控件的平移,我们来逐行分析这段代码。
    ofFloat方法的函数原型,
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
参数含义:
    target:动画操作的对象,我们这里的操作对象就是ImageView控件head
    propertyName:属性名称,这里的"translationX"属性值意思就是在水平方向移动,如果是"translationY"就是在垂直方向移动,下面讲到的其动画效果也是这个意思,这个属性值跟我们在xml文件中设置属性值得名称是一致的,比如
"android:translationY"。
    values:动画过渡值,过渡值可以有一个到N个,如果是一个值的话,就默认是这个动画过渡值的结束值,如果有N个值,动画就在这N个值之间过渡,如本例中有三个过渡值"0.0f, 350.0f, 0f",意思就是从当前位置向右滑到350的位置,再滑到位置0,即初始位置。
    然后是动画的设置,
    objectAnimator.setDuration(2000);//动画的时间间隔
    objectAnimator.setRepeatCount(Animation.INFINITE);//重复次数
    objectAnimator.setRepeatMode(Animation.RESTART);//重复模式
    最后start,动画就开始执行了
     objectAnimator.start();</span>
2.缩放(scale)
// 缩放
private void scaleXAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "scaleX", 1.0f, 1.5f);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}

3.旋转(rotate)
// 旋转
private void rotateAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "rotationX", 0.0f, 90.0f,0.0F);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}

4.透明度(alpha)
// 透明度
private void alphaAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "alpha", 1.0f, 0.3f, 1.0F);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}

    可能我们也注意到了,在缩放效果的实例中,图片被放大后就保持当前的状态,没有变为初始的样子,这是因为我们在设置过渡值是最终的状态是1.5f,就放大到1.5倍,并没有让它回到原来的状态,从这点就可以看出,属性动画是真真切切的可以改变控件的属性的,这是与补间动画的最大不同,补间动画在动画结束后都将回到初始状态。所以说,属性动画的使用就显得更加的灵活。至于上面的其他三个实例,最终回到初始状态,是因为我们在设过渡值的时候最终状态设定的就是初始状态。

刚才我们讨论了几种常见的动画效果,如果仅有这些功能的话,那就与补间动画没有太大的区别。其实,属性动画还可以设置其他的属性值。ObjectAnimator的ofObject方法,就是用来对任意对象进行动画设置的,如字体颜色,直接看实例

<TextView
android:id="@+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:layout_centerInParent="true"
android:textSize="32sp"
android:text="测试颜色变化"/>
int startColor = 0xffff0000;
int endColor = 0xff00ff00;
ObjectAnimator objectAnimator4 = ObjectAnimator.ofObject(txt, "textColor", new TypeEvaluator() {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;

return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}, startColor, endColor);
objectAnimator4.setDuration(3000);
objectAnimator4.start();

    ofObject方法的原型
public static ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)

我们看到它比ofFloat多了一个TypeEvaluator参数,它是用来告知系统如何进行属性值过渡的,由于ofObject是任意属性,所以需要自己实现TypeEvaluator,ofFloat没有该参数是因为系统默认实现了其过渡行为FloatEvaluator,关于TypeEvaluator我们会单独讲解,这边就不在详述了。

除了字体颜色外,还可以设置背景色"backgroundColor"等。

刚才的字体颜色除了使用ofObject方法外,还可以使用ofArgb,但需要SDK版本21上支持,目前市面上很多机型还是21以下的,暂时我们最好不要使用。

ObjectAnimator objectAnimator2 = ObjectAnimator.ofArgb(txt, "textColor", 0x000, 0x00FF00);
objectAnimator2.start();

二、常用设置

在上面的例子中,我们已经对动画进行了一些设置,如间隔、重复次数等等,下面就将常见的设置罗列出来。

1.setInterpolator():设置动画插值
    控制动画的变化速率,系统中定义了好几种Interpolator:

LinearInterpolator--均匀的速率改变


    AccelerateDecelerateInterpolator--先加速后减速
    AccelerateInterpolator--加速
    DecelerateInterpolator--减速

CycleInterpolator--动画循环播放特定的次数,速率改变沿着正弦曲线


2.setDuration():设置动画执行时间,动画时间以毫秒为单位(ms)

3.setRepeatCount():设置动画重复次数
    大于0的值就代表重复几次,如果需要无限循环,设为-1,上面的Animation.INFINITE是系统给的常量,值为-1,代表无限循环,我们建议使用这个常量,如果设为0呢?也是执行一次。4.setRepeatMode():设置动画重复模式
5.setStartDelay():设置动画延时操作,也是以毫秒为单位(ms) 
6.setTarget():设置动画的对象
    操作对象,上面的例子中将动画对象通过ofXXX方传递,如果需要改变动画对象,但动画效果不变,我们可以使用该方法来设置。
objectAnimator.setTarget(txt);//将动画对象head变为txt

7.setEvaluator():设置动画过度的评估者,即设置TypeEvaluator对象,后面会详细介绍

三、组合动画

上面讲到的都是单一的动画,在实际使用时,有可能同时需要多种动画效果,比如同时在水平方向和垂直方向进行缩放并且同时绕水平方向旋转,要实现这样的效果就必须用到组合动画。可以有三种方式来实现,一一讲解。

1.AnimatorSet

AnimatorSet可以让几个动画同时执行,也可以设置执行顺序、延迟执行等,

    after(Animator anim)--将现有动画插入到传入的动画之后执行    after(long delay)--将现有动画延迟指定毫秒后执行    before(Animator anim)--将现有动画插入到传入的动画之前执行    with(Animator anim)--将现有动画和传入的动画同时执行
    playSequentially(Animator... items)--依次执行
private void multiAnimation() {
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(head, "scaleX", 1.0f, 2.5f, 1.0f);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(head, "scaleY", 1.0f, 2.5f, 1.0f);
        ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(head, "rotationX", 0.0f, 90.0f,0.0F);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(objectAnimator1).with(objectAnimator2).with(objectAnimator3);
        animatorSet.setDuration(2000);
        animatorSet.start();
    }

让动画同时执行除了使用with方法外,还可以用playTogether方法,

animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);

其他几种就不在演示了。

2.PropertyValuesHolder

    这种方式只能多个动画一起执行,不同设置先后顺序。
private void multiAnimation2() {
        PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 2.5f, 1.0f);
        PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 2.5f, 1.0f);
        PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 90.0f,0.0F);
        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(head, valuesHolder, valuesHolder1, valuesHolder2);
        objectAnimator.setDuration(2000);
        objectAnimator.start();
}

3.ViewPropertyAnimator

该类是多属性动画,从名字就可以看出该类的作用对象是view,当一个view对象需要同时执行多个属性动画的时候就可以考虑使用该类了。比如说:一个ImageView先右移动的同时进行放大一倍的动画效果实现如下

private void viewPropertyAnimator() {
        ViewPropertyAnimator animator = head.animate();
        animator.translationX(200)
                .scaleX(2)
                .scaleY(2)
                .setDuration(2000)
                .start();
    }

四、动画的监听

一般情况下,我们除了需要动画效果外,还需要对动画的执行过程进行监听,在执行前、执行结束后或者执行过程中,做出相应的处理,比如动画结束后,请求网络数据。系统给我们提供几种监听接口,来监听动画的各个状态,如AnimatorListener,

private void animationListener() {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f);
        objectAnimator.setDuration(2000);
        objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                Log.d("dingfeng", "onAnimationStart......");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d("dingfeng", "onAnimationEnd......");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                Log.d("dingfeng", "onAnimationCancel......");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                Log.d("dingfeng", "onAnimationRepeat......");
            }
        });
        objectAnimator.start();
    }
    可以根据不同需求来实现接口里面的四个方法,可以根据需要做相应的处理。但有时候你会觉得我不需要监听动画的四种状态,我只需要监听动画结束时候的状态,使用上面的方法就会感觉代码臃肿了,不过没关系,Android系统给我们提供了一个更好用的方法,
private void animationListener2() {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f);
        objectAnimator.setDuration(2000);
        objectAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                Log.d("dingfeng", "onAnimationEnd......");
            }
        });
        objectAnimator.start();
    }
    可以看出,我们使用了AnimatorListenerAdapter动画接口适配器代替AnimatorListener接口。其实AnimatorListenerAdapter的源码只是一个实现了AnimatorListener接口的抽象类而已,    你需要监听哪种动画状态就重写哪种方法就可以了。    除此之外,AnimatorUpdateListener接口就可以读取到动画的每个更新值。
private void animationListener3() {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f);
        objectAnimator.setDuration(2000);
        objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float)animation.getAnimatedValue();
                Log.d("dingfeng", "onAnimationUpdate......"+value);
            }
        });
        objectAnimator.start();
    }

一般情况下不太用到这个接口,但是在自定义动画的时候,通过该接口,可以实现很多复杂的效果。


五、xml编写动画

当然,我们也可以在xml文件中配置动画,这样做可以比较好的复用这些动画,减少代码量。

1.在资源目录下创建animator文件夹

将编写的xml文件放在该目录下,如下图

我们创建两个动画文件,一个是旋转动画,一个组合动画

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android='http://schemas.android.com/apk/res/android'
android:duration='2000'
android:propertyName='rotationX'
android:repeatCount="-1"
android:repeatMode="restart"
android:valueFrom='0'
android:valueTo='180'
android:valueType='floatType' />
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android='http://schemas.android.com/apk/res/android'
android:duration='2000'
android:ordering='sequentially'><!--动画执行顺序 sequentially:顺序执行;together:同时执行。 -->
<objectAnimator
android:propertyName='translationX'
android:valueFrom='0'
android:valueTo='200'
android:valueType='floatType' />

    <set android:ordering='together'>
        <objectAnimator
        android:propertyName='scaleX'
        android:valueFrom='1'
        android:valueTo='2'
        android:valueType='floatType' />
        <objectAnimator
        android:propertyName='scaleY'
        android:valueFrom='1'
        android:valueTo='2'
        android:valueType='floatType' />
    </set>
</set>

2.加载动画

使用AnimatorInflater加载动画文件

head = (ImageView) findViewById(R.id.head);
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.multi);
animator.setTarget(head);
animator.start();

这样就OK了,还是很容易的。

时间: 2024-10-12 10:21:36

属性动画之ObjectAnimator的相关文章

【转】android 属性动画之 ObjectAnimator

原文网址:http://blog.csdn.net/feiduclear_up/article/details/39255083 前面一篇博客讲解了 android 简单动画之 animtion,这里来讲解一下android 3.0之后添加的一些动画   animator 中的 ObjectAnimator . 属性动画概念: 所谓属性动画:改变一切能改变的对象的属性值,不同于补间动画:只能改变 alpha,scale,rotate,translate.听着有点抽象,举例子说明 补间动画能实现的

Android属性动画之ObjectAnimator

相信对于Android初学者,对于Android中的动画效果一定很感兴趣,今天为大家总结一下刚刚学到的属性动画案例. 首先和一般的Android应用一样,我们先建一个工程,为了方便,我们的布局文件中就只添加一个ImageView和button按钮,代码如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andr

Android 属性动画框架 ObjectAnimator、ValueAnimator ,这一篇就够了

前言 我们都知道 Android 自带了 Roate Scale Translate Alpha 多种框架动画,我们可以通过她们实现丰富的动画效果,但是这些宽家动画却有一个致命的弱点,它们只是改变了 View 显示的大小,而没有改变 View 的响应区域.这时以 ObjectAnimator.ValueAnimator 为代表的属性动画也就应运而生了. 简单效果 工作原理 属性动画字如其名,是通过改变 View 的属性值来改变控件的形态,说白了就是通过反射技术来获取控件的一些属性如宽度.高度等的

android 属性动画之 ObjectAnimator

前面一篇博客讲解了 android 简单动画之 animtion,这里来讲解一下android 3.0之后添加的一些动画   animator 中的 ObjectAnimator . 1.alpha //第一个参数为 view对象,第二个参数为 动画改变的类型,第三,第四个参数依次是开始透明度和结束透明度. ObjectAnimator alpha = ObjectAnimator.ofFloat(text, "alpha", 0f, 1f); alpha.setDuration(20

Android属性动画之ObjectAnimator控制

Android为我们提供了大量的动画效果,如何通过这些动画来达到我们需要的效果呢?今天就为大家总结一下ObjectAnimator动画控制事件. 该项目的的布局文件只有两个控件:ImageView和Button,在这里就不在赘述了,下面我们来看一下activity的实现: public class TwoActivity extends Activity{ private Button button;private ImageView imageView; @Override protected

android学习(属性动画扇形菜单栏)

1 public class TestActivity extends Activity implements OnClickListener{ 2 private int[] res={R.id.imageView1,R.id.imageView2,R.id.imageView3,R.id.imageView4,R.id.imageView5,R.id.imageView6}; 3 private List<ImageView> list=new ArrayList<ImageView

Android用属性动画拖动view到任意位置

直接上图: 代码: package me.waye; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageVie

浅谈属性动画简单使用之实现卫星菜单(二)

大家对于卫星菜单应该都不陌生了,其实这个菜单如果能合适运用到我们的APP项目中,确实是一个不错的选择,交互性非常好.在写Demo之前我也上网搜了一些关于卫星菜单的实现,感觉好多人实现卫星菜单这种动画,采用的是补间动画,并且代码还不少,通过上一讲我们知道,补间动画不具备与用户交互的特点,就比如卫星菜单展开后,产生很多子菜单有很多的点击事件,会发现产生点击事件的位置不会随着补间动画而产生位置改变而改变,反而点击事件一直保存在初始的位置.当然补间动画也能做,那就需要产生动画后发生位置的改变,并且也需要

Android动画——属性动画

一.概述 Android在API11后加入的新特性,主要通过对对象的属性动态改变实现动画效果,也因此大大扩展了作用对象,并且由于直接对属性进行变换,动画效果也更丰富.主要有ValueAnimator.ObjectAninmator.AnimatorSet等概念. 二.属性动画的分类及使用 1.ObjectAnimator 继承自ValueAnimator,使用举例如下 ObjectAnimator.ofFloat(button,"translationY",100).setDurati