我们在上一篇博客中,讨论了视图动画与帧动画。那么这节课则要讨论更复杂,更强大的Property animation(属性动画)。

视图动画使用简单,但是功能也简单。(只有那四种功能)。并且也不改变View的真实布局属性值。帧动画主要是依靠ui设计师切图。而android3.0之后,推出了属性动画,则是功能强大,可以能让我们自由发挥想象力。

Android3.0以下版本也有支持库 NineOldAndroids,不过其作者,大名鼎鼎的JakeWharton大神已经表示该库已经不再维护更新了。不过Android3.0的android机在市场上应该早就消失殆尽了。

在具体讨论之前,我们先来熟悉两个概念:插值器估值器

插值器和估值器

TimeInterpolator中文翻译为时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比。系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)和DecelerateInterpolator(减速插值器:动画越来越慢)等;TypeEvaluator的中文翻译为类型估值算法,也叫作估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)和ArgbEvaluator(针对Color属性)。

光说枯燥无味的概念肯定是羞涩难懂。所以借用google官方给的实例来理解。

下图是一个匀速动画,采用线性插值器和整型估值算法。在40ms内,view的X属性从0到40变换。

动画默认刷新频率是10ms/帧,所以该动画要分为5帧来进行,我们来考虑第三帧,(也就是最中间一帧)。此时t=20ms,所以时间流逝的百分比是0.5(20/40)。也就是时间插值器得出的百分比是0.5。那么x等于多少呢。因为匀速,所以此时x=20,所以估值器计算得出的值就是20。

再说一个更加通俗易懂的例子。要求运动员60分钟跑完一万米,他可以采用各种不同的跑步策略,比如匀速跑,也可以先慢慢跑节省体力,然后最后阶段再加速冲刺, 或者先快跑后慢跑,总之,他怎么跑都行,只要最后能完成目标,在第60分钟时跑到一万米的终点就好了。在该过程的某个节点上,时间插值器的作用是估算运动员已使用的时间占总时间(就是60分钟)的百分比,而估值器则是估算出该运动员目前跑了多少米。

TimeInterpolatorTypeEvaluator都是interface,所以也可以直接继承它们,定义符合我们特殊需求的插值器和估值器。这在很多模拟自然物理特性的动画中要用到。比如动画模拟一个小球下落的轨迹,这是一个重力加速过程,肯定不是匀速动画。

Property Animation

属性动画,顾名思义,就是对对象的属性进行改变。(并不局限于View),默认帧率为10ms/帧,其实就是说:在指定的时间间隔内(时间插值器决定),将该对象的属性值改变多少(估值器决定)。比如,可以将对象的透明度在1s之内从0变化为1.这就是一个改变属性值的过程。并且是在每间隔10ms,重新调用setAlpha方法重新进行绘制。但其实这不就是 AlphaAnimation做的事情嘛。所以说属性动画更强大,并且可以替代视图动画。(当然视图动画简单易用,这是优点)。

既然说白了,属性动画就是通过每间隔10ms,就调用View的属性值设置方法进行改变的过程,那么常用的View属性有哪些呢。

  • translationXtranslationY:控制View的位置,值是相对于View容器左上角坐标的偏移。
  • rotation,rotationXrotationY:控制View对象围绕支点进行旋转。
  • scaleX,scaleY:围绕支点进行2D缩放。
  • pivotX, pivotY:这两个属性控制着View对象的支点位置,旋转缩放等操作的中心点就是该支点,默认该支点位置就是View对象的中心点。
  • xy:控制View在容器中的位置,即左上角坐标加上translationX和translationY的值。
  • alpha:控制View对象的alpha透明度值。默认1(不透明),0代表完全透明。

关于属性动画,我们最常用的类型有以下几种,ValueAnimator,ObjectAnimatorAnimatorSet

在xml中定义属性动画,文件路径如下:res/animator/fileName.xml,具体定义形式如下:

<set
android:ordering=["together" | "sequentially"]> <objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/> <animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/> <set>
...
</set>
</set>

set相关属性:

xml属性 解释
android:ordering 控制子动画启动方式是先后有序的还是同时进行。sequentially:动画按照先后顺序;together(默认):动画同时启动;

objectAnimatoranimator 相关属性:

xml属性 解释
android:propertyName String类型,必须要设置的节点属性,代表要执行动画的属性(通过名字引用),辟如你可以指定了一个View的”alpha” 或者 “backgroundColor” ,这个objectAnimator元素没有对外说明target属性,所以你不能在XML中设置执行这个动画,必须通过调用loadAnimator()方法加载你的XML动画资源,然后调用setTarget()应用到具备这个属性的目标对象上(譬如TextView)。
android:valueTo float、int或者color类型,必须要设置的节点属性,表明动画结束的点;如果是颜色的话,由6位十六进制的数字表示。
android:valueFrom 相对应valueTo,动画的起始点,如果没有指定,系统会通过属性的get方法获取,颜色也是6位十六进制的数字表示。
android:duration 动画的时长,int类型,以毫秒为单位,默认为300毫秒。
android:startOffset 动画延迟的时间,从调用start方法后开始计算,int型,毫秒为单位。
android:repeatCount 一个动画的重复次数,int型,”-1“表示无限循环,”1“表示动画在第一次执行完成后重复执行一次,也就是两次,默认为0,不重复执行。
android:repeatMode 重复模式:int型,当一个动画执行完的时候应该如何处理。该值必须是正数或者是-1,“reverse”会使得按照动画向相反的方向执行,可实现类似钟摆效果。“repeat”会使得动画每次都从头开始循环。
android:valueType 关键参数,如果该value是一个颜色,那么就不需要指定,因为动画框架会自动的处理颜色值。有intType和floatType(默认)两种:分别说明动画值为int和float型。

而在代码中,我们这样来使用我们设置的xml文件。

//@author www.yaoxiaowen.com
//本文地址 :http://www.cnblogs.com/yaoxiaowen/p/7501202.html
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animtor.fileName);
set.setTarget(myObject);
set.start();

ObjectAnimator

ObjectAnimator extends ValueAnimator ,它允许指定某个对象以及该对象的一个属性。该类会根据计算得到的新值自动更新这个对象的属性。ObjectAnimator其实算是对ValueAnimator的包装,它使我们的处理过程变的简单,因为ValueAnimator还要自己手动去写更新逻辑。所以大部分情况下,我们使用ObjectAnimator就足够了。

使用方式:

//@author www.yaoxiaowen.com
//本文地址 :http://www.cnblogs.com/yaoxiaowen/p/7501202.html
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(mView, "rotationX", 0, 360),
ObjectAnimator.ofFloat(mView, "rotationY", 0, 180),
ObjectAnimator.ofFloat(mView, "rotation", 0, 90),
ObjectAnimator.ofFloat(mView, "translationX", 0, 90),
ObjectAnimator.ofFloat(mView, "translationY", 0, 90),
ObjectAnimator.ofFloat(mView, "scaleX", 1, 1.5f),
ObjectAnimator.ofFloat(mView, "scaleY", 1, 1.5f),
ObjectAnimator.ofFloat(mView, "alpha", 1, 1.5f, 1)
);
set.setDuration(5000).start();
  • ObjectAnimator 提供了 ofIntofFloatofObject这三个默认方法来设置动画作用的元素,属性,动画开始,结束以及中间的任意属性值。
  • 而对于 from和to一对属性值,如果只设置了一个值,则认为From的值就是该View的当前值,设置的值就是To终点值,当然如果设置了两个,则一个是From值,一个是To值。
  • 如果操作View的某种属性方法里面,比如setRotationX内部没有调用View的重绘。或者设置的的object不是View,那么就需要我们自己执行相关刷新操作了。(否则你使用了ObjectAnimator也没任何效果)。
anim.addUpdateListener(new AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
// view.postInvalidate();
// view.invalidate();
// 或者 其他操作 }
});
  • 我们前面就强调过,属性动画其实实质上就是不断的调用 setXXX来更新元素的属性罢了。所以既然使用了 ObjectAnimator那么这个属性就必须有对应的set,get方法。可如果某些属性没有这个相应的set,get方法咋整呢(比如View元素的宽高),其实Android也提供了对应的解决方案。使用一个包装类进行包装,间接提供set,get方法就可以了。
private void performAnimate() {
ViewWrapper wrapper = new ViewWrapper(mButton);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
} //包装类
private static class ViewWrapper {
private View mTarget; public ViewWrapper(View target) {
mTarget = target;
} public int getWidth() {
return mTarget.getLayoutParams().width;
} public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}

ValueAnimator

ValueAnimator其实才是属性动画的核心,它是比ObjectAnimator更加抽象的动画类,它本身不产生什么具体动画效果。但它设置了作用间隔等,进行相应的驱动。说的通俗点,它更像一个数值发生器,产生具有一定规律的数字,通过监听函数,从而让调用者自己去控制究竟实现什么功能。(所以它自然也不要求操作对用有set,get方法)。

它的常用使用方式如下:

ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
animator.setTarget(view); //设置作用目标
animator.setDuration(5000).start();
animator.addUpdateListener(new AnimatorUpdateListener() {
//每更新一帧,都会进行回调
@Override
public void onAnimationUpdate(ValueAnimator animation){
float value = (float) animation.getAnimatedValue();
// 做一些我们的自定义操作 //@author www.yaoxiaowen.com
//本文地址 :http://www.cnblogs.com/yaoxiaowen/p/7501202.html
}
});

动画事件的监听

一个完整的动画具有Start,Repeat,End,Cancel四个过程,我们可以通过监听事件来监听对应的事件。

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha",0.5f);
anim.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) {
}
});

当然,四个监听方法虽全,但是太繁琐了,很多时候,我们只关心其中的某一个事件,所以Android也提供了对应的简化版本api。使用AnimatorListenerAdapter监听对象,AnimatorListenerAdapter implements Animator.AnimatorListener ,它是类而不是接口,我们可以自由选择实现一个或多个监听方法。

除此之外,还有很重要的 ValueAnimator.AnimatorUpdateListener接口,我们在前面也已经使用过,每帧发生变化时,都会调用该接口。

anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//一般此时需要进行强制类型转化
Object obj = animation.getAnimatedValue();
}
});

PropertyValuesHolder

类似视图动画中的AnimationSet,针对同一个对象的多个属性,同时作用于多种动画.

使用方式如下:

PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();

AnimatorSet

和前面的 PropertyValuesHolder类似,但是 AnimatorSet 除了有同时作用于多种动画的作用之外,它还能实现更为精准的顺序控制,比如同时播放,顺序播放,延迟播放等。

ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);
ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth);
......
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(5000);
animSet.setInterpolator(new LinearInterpolator());
//animSet.playTogether(a1, a2, ...); //两个动画同时执行
animSet.play(a1).after(a2); //先后执行
......//其他组合方式
animSet.start(); //@author www.yaoxiaowen.com
//本文地址 :http://www.cnblogs.com/yaoxiaowen/p/7501202.html

其他问题。

结合自己写demo时的犯下的小错误,有以下几点要注意一下:

  • 属性动画类的拼写是Animator,不是视图动画的Animation,两者的继承关系也不一样,不要拼写错了。像那些具体的属性值之类的,也要注意不要拼写错误了。
  • 在具体设置某种属性的时候,要注意是 int 还是float类型。不要想当然,我写了个demo,设置 rotation,我觉的是int,试了几遍没反应,后来才发现是 float类型,记不清楚的去查看api文档。

作者:
www.yaoxiaowen.com

博客地址:
www.cnblogs.com/yaoxiaowen/

github:
https://github.com/yaowen369

欢迎对于本人的博客内容批评指点,如果问题,可评论或邮件(yaowen369@gmail.com)联系

<p >
欢迎转载,转载请注明出处.谢谢
</p> <script type="text/javascript">
function Curgo()
{
window.open(window.location.href);
}
</script>

Android动画(二)-属性动画的更多相关文章

  1. android 学习随笔二十六(动画:属性动画)

    属性动画,属性动画是真正改变对象的某个属性的值 * 补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变1.位移:* 第一个参数target指定要显示动画的组件* 第二个参数proper ...

  2. Android动画基础——属性动画(Property Animation)

    本篇涉及例子下载:Github 本篇讲android 3.0引入的属性动画框架,上篇写视图动画View Animation时就说过ViewAnimation的缺点,那就是动画作用的是view本身的视觉 ...

  3. Android笔记之属性动画

    前言.动画分类 例如以下图所看到的,Android的动画主要分为三种: 以下首先说说 属性动画 所谓属性动画-- 就是指对象的属性值发生了变化,如控件位置和透明度等. 举例,如今要实现一个按键先下移. ...

  4. Android开发实战之补间动画和属性动画

    说起动画,其实一点也不陌生,在使用一款app的时候为了优化用户体验,多多少少的,都会加入动画. 安卓中的动画,分为两大类:补间动画和属性动画.本篇博文会详细介绍总结这两大动画,希望本篇博文对你的学习和 ...

  5. Android开发——View动画、帧动画和属性动画详解

    0. 前言   Android动画是面试的时候经常被问到的话题.我们都知道Android动画分为三类:View动画.帧动画和属性动画. 先对这三种动画做一个概述: View动画是一种渐进式动画,通过图 ...

  6. View动画和属性动画

    在应用中, 动画效果提升用户体验, 主要分为View动画和属性动画. View动画变换场景图片效果, 效果包括平移(translate), 缩放(scale), 旋转(rotate), 透明(alph ...

  7. android104 帧动画,补间动画,属性动画

    ##帧动画FrameAnimation* 多张图片快速切换,形成动画效果* 帧动画使用xml定义 package com.itheima.frameanimation; import android. ...

  8. android动画具体解释二 属性动画原理

    property动画是一个强大的框架,它差点儿能使你动画不论什么东西. 你能够定义一个动画来改变对象的不论什么属性,不论其是否被绘制于屏幕之上. 一个属性动画在一定时间内多次改变一个属性(对象的一个字 ...

  9. Android 动画及属性动画

    Android 平台提供了一套完整的动画框架,在Android3.0之前有两种动画Tween Animation(补间动画)和Frame Animation(帧动画), 对应SDK中的View Ani ...

随机推荐

  1. Python的Web应用框架--Django

    一:简介 python的web框架有很多,个人查了一下,有Django.Pylons. Tornado.Bottle和Flask等,其中使用人数最多的是Django,而我学习Django也是因为ope ...

  2. onload和ready的区别

    onload和ready的区别 1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行 $(document).read()是DOM结构绘制完毕后就执行,不必等到加 ...

  3. 从头认识Spring-2.7 自己主动检測Bean(2)-过滤器&lt;context:include-filter/&gt;

    这一章节我们来讨论一下过滤器<context:include-filter/>的使用. 1.domain Person接口: package com.raylee.my_new_sprin ...

  4. F12调试模式下使用console自动提交

    F12调试模式下使用console自动提交(F12 的console->输入代码->按enter即可运行) 1.使用定时器setInterval进行自动提交 //方法中可使用jquery调 ...

  5. 服务器固件测试--PCI设备的介绍(集成网卡和外插网卡)

    今天2017年9月26号,快三个月的时间,是该梳理一下,我来到这个岗位学到的东西. 网卡是什么 网卡分为俩大类 板载的集成网卡和外插的网卡.外插的网卡又分为很多种. 板载的集成网卡 外插的网卡分为 I ...

  6. 自学Python3.2-函数分类

    函数的分类 内置函数,自定义函数,匿名函数 一.内置函数(python3.x) 内置参数详解官方文档: https://docs.python.org/3/library/functions.html ...

  7. Tuxedo:Tuxedo支持的分布式通信方式

    1.RPC:用于远程方法调用.Java中类似的技术有EJB.WebService 2.Conversaction:交流.Java中类似的有JDBC. 3.Message Notification:消息 ...

  8. Asynchronous MQTT client library for C (MQTT异步客户端C语言库-paho)

    原文:http://www.eclipse.org/paho/files/mqttdoc/MQTTAsync/html/index.html MQTT异步客户端C语言库   用于C的异步 MQTT 客 ...

  9. IDEA使用--字体、编码和基本设置

    IDEA这么高端的工具之前只是断断续续使用了一下,因为项目的开发都是在eclipse上,每次学习IDEA的使用都得上网搜索半天,今天自己整理一下,方便以后查阅. IDEA版本15.0.4 字体 界面字 ...

  10. AutoFac+ASP.NetMvc,AspNet.Core

    ASP.Net.Mvc 引用 install-package autofac install-package Mvc5 //创建一个用于注册的对象 ContainerBuilder builder = ...