Android动画(二)-属性动画
我们在上一篇博客中,讨论了视图动画与帧动画。那么这节课则要讨论更复杂,更强大的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分钟)的百分比,而估值器则是估算出该运动员目前跑了多少米。
TimeInterpolator
和TypeEvaluator
都是interface
,所以也可以直接继承它们,定义符合我们特殊需求的插值器和估值器。这在很多模拟自然物理特性的动画中要用到。比如动画模拟一个小球下落的轨迹,这是一个重力加速过程,肯定不是匀速动画。
Property Animation
属性动画,顾名思义,就是对对象的属性进行改变。(并不局限于View),默认帧率为10ms/帧,其实就是说:在指定的时间间隔内(时间插值器决定),将该对象的属性值改变多少(估值器决定)。比如,可以将对象的透明度在1s之内从0变化为1.这就是一个改变属性值的过程。并且是在每间隔10ms,重新调用setAlpha
方法重新进行绘制。但其实这不就是 AlphaAnimation
做的事情嘛。所以说属性动画更强大,并且可以替代视图动画。(当然视图动画简单易用,这是优点)。
既然说白了,属性动画就是通过每间隔10ms,就调用View的属性值设置方法进行改变的过程,那么常用的View属性有哪些呢。
translationX
,translationY
:控制View的位置,值是相对于View容器左上角坐标的偏移。rotation
,rotationX
,rotationY
:控制View对象围绕支点进行旋转。scaleX
,scaleY
:围绕支点进行2D缩放。pivotX
,pivotY
:这两个属性控制着View对象的支点位置,旋转缩放等操作的中心点就是该支点,默认该支点位置就是View对象的中心点。x
,y
:控制View在容器中的位置,即左上角坐标加上translationX和translationY的值。alpha
:控制View对象的alpha透明度值。默认1(不透明),0代表完全透明。
关于属性动画,我们最常用的类型有以下几种,ValueAnimator
,ObjectAnimator
和AnimatorSet
。
在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(默认):动画同时启动; |
objectAnimator
或 animator
相关属性:
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
提供了ofInt
,ofFloat
和ofObject
这三个默认方法来设置动画作用的元素,属性,动画开始,结束以及中间的任意属性值。- 而对于 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.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动画(二)-属性动画的更多相关文章
- android 学习随笔二十六(动画:属性动画)
属性动画,属性动画是真正改变对象的某个属性的值 * 补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变1.位移:* 第一个参数target指定要显示动画的组件* 第二个参数proper ...
- Android动画基础——属性动画(Property Animation)
本篇涉及例子下载:Github 本篇讲android 3.0引入的属性动画框架,上篇写视图动画View Animation时就说过ViewAnimation的缺点,那就是动画作用的是view本身的视觉 ...
- Android笔记之属性动画
前言.动画分类 例如以下图所看到的,Android的动画主要分为三种: 以下首先说说 属性动画 所谓属性动画-- 就是指对象的属性值发生了变化,如控件位置和透明度等. 举例,如今要实现一个按键先下移. ...
- Android开发实战之补间动画和属性动画
说起动画,其实一点也不陌生,在使用一款app的时候为了优化用户体验,多多少少的,都会加入动画. 安卓中的动画,分为两大类:补间动画和属性动画.本篇博文会详细介绍总结这两大动画,希望本篇博文对你的学习和 ...
- Android开发——View动画、帧动画和属性动画详解
0. 前言 Android动画是面试的时候经常被问到的话题.我们都知道Android动画分为三类:View动画.帧动画和属性动画. 先对这三种动画做一个概述: View动画是一种渐进式动画,通过图 ...
- View动画和属性动画
在应用中, 动画效果提升用户体验, 主要分为View动画和属性动画. View动画变换场景图片效果, 效果包括平移(translate), 缩放(scale), 旋转(rotate), 透明(alph ...
- android104 帧动画,补间动画,属性动画
##帧动画FrameAnimation* 多张图片快速切换,形成动画效果* 帧动画使用xml定义 package com.itheima.frameanimation; import android. ...
- android动画具体解释二 属性动画原理
property动画是一个强大的框架,它差点儿能使你动画不论什么东西. 你能够定义一个动画来改变对象的不论什么属性,不论其是否被绘制于屏幕之上. 一个属性动画在一定时间内多次改变一个属性(对象的一个字 ...
- Android 动画及属性动画
Android 平台提供了一套完整的动画框架,在Android3.0之前有两种动画Tween Animation(补间动画)和Frame Animation(帧动画), 对应SDK中的View Ani ...
随机推荐
- Sql Server 的服务器类型
Sql Server 提供了四种服务器类型: 如图所示 : 1, 数据库引擎 2, Analysis Services (分析服务 ) 3, Reporting Services (报告服务) ...
- poj 2905 双向队列(待补充)
Parallel Computer Simulator Description Programs executed concurrently on a uniprocessor system ap ...
- Java面试题集合(比较实用)
1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用...... ...
- Java爬虫——人人网模拟登录
人人网登录地址:http://www.renren.com/ 此处登录没有考虑验证码验证码. 首先对登录方法进行分析 有两种方法. 一)在Elements中分析源码 发现登录点击后的事件是http:/ ...
- 第一次面试&第一次霸面
哈哈哈哈,第一次面试和第一次都献给了CVTE! CVTE的招聘流程有点特别:网測-- 一面--笔试--二面--offer 想起网測那天就心酸.那先在做第三部分的专业測试.计时器突然出错........ ...
- AB串
题目: 给定n个A和2n个B.用这些字符拼成一个字符串.要求这个串的全部前缀和后缀B的个数始终不少于A. (一个字符串的前缀是仅仅从开头到某个位置为止的子串,后缀是仅仅从某个位置到结尾的子串). 输入 ...
- OpenTK教程-0序言
记得很久之前,我写过一个基于.NET的3D开发框架/工具比较.当时选定的技术是WPF.但是随着项目发展,需要处理的图形数量越来越多,基于WPF的处理起来性能有问题,最后还是使用了基于OpenTK的解决 ...
- Jsp制作验证码
验证码 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart&qu ...
- 《跟我学IDEA》四、配置模板(提高代码编写效率)
上一篇博文,我们学习了idea的一些实用配置,相信大家也对idea这个开发工具有了一个大概的了解.今天我们来学习模板的配置,idea提供很多模板从而提高编写代码的效率,比如说一些经常用的代码及生成文件 ...
- intellij idea的安装步骤---经典
安装IntelliJ IDEA 一.安装JDK 1 下载最新的jdk,这里下的是jdk-8u66 2 将jdk安装到默认的路径C:\Program Files\Java目录下 二.安装IntelliJ ...