【Android】属性动画
转载请注明出处:http://blog.csdn.net/h28496/44338669
属性动画的原理
通过不断的设置一个View的属性让其出现动画效果。比如,不断地设置一个Button的x值。这个button就会在y轴上运动。
假设学过flash或者其它动画制作的话。应该能理解“补间动画”的意思。属性动画类似于属性上的补间动画。
设置一个View的初始值和结束值,属性动画会随着时间的变化,逐渐地把View的属性从初始值变化到结束值。
实现属性动画的条件
由属性动画的原理可知,要实如今某个方面的动画。首先这个View得有这个属性。即,要有 set属性名() 和 get属性名()方法。
比如:setWidth(), getWidth()。
注意:button自带的getWidth() 和 setWidth()在这里是没有效果的。回忆一下在代码中设置一个button的宽度是怎么设置的?
在代码中设置宽度:
- button.getLayoutParams().width = 100;
它相应于xml文件里的是
- android:layout_width
而不是
- android:width
至于width有什么用,我感觉没什么用……看过其它大牛写的博客。也是不太清楚android:width有什么用。
一个简单的样例
效果:点击了Button之后按x轴翻转。
Button的布局文件非常普通。不贴了。
- public void onClick(View view) {
- ObjectAnimator
- .ofFloat(view, "rotationX", 0f, 360f)
- .setDuration(1000)
- .start();
- }
解释一下:由于Button这个类存在 setRotationX(float p)这种方法。所以第三行的第二个參数 “rotationX” 是有效的。
假设写的是一个不存在的參数,或者设置的參数和画面无关,那么画面是没有动画的。
另外,因为setRotationX(float p)的參数类型是float型的,所以第三行用的是 ofFloat(...) 而不是 ofInt(...)或者其它。
setDuration(int p)是动画的时长。单位毫秒。
我在看任玉刚大牛写的博客时他写道,假设没有set属性名()这种方法会导致程序崩溃。但我实測时没有崩溃,仅仅是在logcat报了一条错误,程序继续执行。
假设条件不满足怎么办
假设你想给某个View设置一个动画,可是它没有相应的设置属性的方法怎么办?比如:
我们想给button设置一个宽度逐渐变宽的动画,可是button的setWidth()不能设置显示宽度。
解决的办法:
① 加上set属性()、get属性()方法;(除非是你自己定义的控件,否则一般没有权限这么做,以下就不讨论这样的情况了)
② 用一个类去包装原始的对象。间接的提供get、set方法;
③ 採用ValueAnimation获得每个时刻的属性值,然后通过AnimatorUpdateListener监听器依据获得的属性值设置View的状态。
包装原始对象
用这样的方式为一个不存在某种方法的类加入方法非经常见。考虑到多态,通常包装比继承要好得多。
以下是用MyView包装View的样例:
- class MyView{
- View view;
- public MyView(View view){
- this.view = view;
- }
- public int getWidth(){
- return view.getLayoutParams().width;
- }
- public void setWidth(int width){
- this.view.getLayoutParams().width = width;
- this.view.requestLayout(); // 这句话用来又一次设置view的位置
- }
- }
有了包装类。我们就来实现一个让Button(它是继承自View的)宽度变宽的动画吧。
效果:在300毫秒内,view的宽度先变成4倍,再恢复到原来的样子。
- public void onClick(View v) {
- MyView view = new MyView(v);// 先包装一下
- int startWidth = v.getWidth();
- ObjectAnimator.ofInt(view, "width", startWidth, startWidth * 4, startWidth)
- .setDuration(300)
- .start();
- }
使用ValueAnimator和AnimatorUpdateListener自己实现
效果:在一秒的时间内,view从y = 0,移动到 y = 500的地方。
- public void onClick(final View view){
- final ValueAnimator anim = ValueAnimator.ofFloat(0, 500);
- anim.setDuration(1000);
- anim.start();
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float value = (Float) animation.getAnimatedValue();
- view.setTranslationY(value);
- }
- });
- }
先定义一个值动画(ValueAnimator,中文名个人是意译的)。从名称能够看出,它仅仅是一个“值”的变化,并不涉及到详细的视图。
然后再对这个值动画设置一个监听器。每次值有变化的时候。都将这个值应用到视图的属性上去。
比如。值每变化一次,都要又一次设置一下位置。
尽管看起来麻烦了一点。但灵活性更高了。
多个动画同一时候运行
上面的三个样例中。动画都是单独一个。假设我想要在它移动的同一时候还要改变它的透明度怎么办呢?
① 和上面的类似。能够利用AnimatorUpdateListener实现。
② 利用PropertyValuesHolder实现;
③ 利用AnimatorSet实现。
利用AnimatorUpdateListener实现
上一个样例中仅仅设置了视图的位置,但实际上能够同一时候将视图的多个属性设置为那个值。
仅仅需多加几个.set属性()。
这里为了避免反复,不使用ValueAnimator,而是使用ObjectAnimator。
效果:被点击的视图在1秒内。先变小同一时候颜色减淡到无,之后再恢复到原状。(建议使用一个ImageView而不是Button,效果更好)
- public void onClick(final View v){
- ObjectAnimator anim = ObjectAnimator.ofFloat(v, "", 1, 0, 1)
- .setDuration(1000);
- anim.start();
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float currentValue = (Float) animation.getAnimatedValue();
- v.setScaleX(currentValue);
- v.setScaleY(currentValue);
- v.setAlpha(currentValue);
- }
- });
- }
ObjectAnimator和ValueAnimator一样,也是能够加入监听器的。
利用PropertyValuesHolder实现
这样的实现方式代码非常简洁,一看便懂。
效果:被点击的视图在1秒内,先变小、颜色减淡到无,之后再恢复到原状,同一时候整个过程视图旋转了360度。(建议使用一个ImageView而不是Button,效果更好)
- public void onClick(View view){
- PropertyValuesHolder x = PropertyValuesHolder.ofFloat("scaleX", 1, 0, 1);
- PropertyValuesHolder y = PropertyValuesHolder.ofFloat("scaleY", 1, 0, 1);
- PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1, 0, 1);
- PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 0, 360);
- ObjectAnimator.ofPropertyValuesHolder(view, x, y, alpha, rotation).setDuration(1000).start();
- }
利用AnimatorSet实现
从名字能够看出。这是一个动画的集合。AnimatorSet能够让多个动画同一时候执行、先后执行。
同一时候执行
效果:被点击的视图在X方向变大的同一时候。Y方向也变大。之后又同一时候缩小(建议使用一个ImageView而不是Button,效果更好)
- public void togetherRun(View view){
- // 感觉和PropertyValuesHolder差点儿相同
- ObjectAnimator x = ObjectAnimator.ofFloat(view, "scaleX", 1, 2, 1);
- ObjectAnimator y = ObjectAnimator.ofFloat(view, "scaleY", 1, 2, 1);
- AnimatorSet animSet = new AnimatorSet();
- animSet.setDuration(1000);
- animSet.playTogether(x, y);
- animSet.start();
- }
playTogether(Animator... items)能够让多个动画同一时候运行。除此之外。还有playWidth(Animator item)能够让两个动画同一时候运行。
先后执行
效果:被点击的视图在X、y方向变大又缩小,之后再平移到右边并返回(建议使用一个ImageView而不是Button。效果更好)
- public void playAfter(View view){
- ObjectAnimator scaleX = ObjectAnimator.ofFloat(ball, "scaleX", 1, 2, 1);
- ObjectAnimator scaleY = ObjectAnimator.ofFloat(ball, "scaleY", 1, 2, 1);
- ObjectAnimator x = ObjectAnimator.ofFloat(ball, "x", ball.getX(), ball.getX() + 200, ball.getX());
- AnimatorSet animSet = new AnimatorSet();
- // 支持链式编程
- animSet.play(scaleX).with(scaleY);
- animSet.play(x).after(scaleY);
- animSet.setDuration(1000);
- animSet.start();
- }
- }
在先后运行的时候,还能够调用animSet.play(x).after(延迟时间); 使得下一个动画延迟播放。
这里使用的是animSet.play(x).after(scaleY); 即在还有一个动画播放完之后再播放,也能够使用
- animSet.play(x).before(anim1);
让一个动画在还有一个动画播放前播放。
怎样监听动画的结束
animation有三种监听器:
① AnimatorUpdateListener(监听在动画运行过程中的数据或其他情况)
② AnimatorListener(监听动画的‘生命周期’)
③ AnimatorPauseListener(监听动画的暂停与恢复)
有时我们须要在动画结束之后做点事。比如:在点击一个button结束后跳转到还有一个Activity。
这时我们仅仅需让动画加入一个AnimatorListener监听器。
- anim.addListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- // TODO Auto-generated method stub
- }
- @Override
- public void onAnimationRepeat(Animator animation) {
- // TODO Auto-generated method stub
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- // TODO Auto-generated method stub
- // 在这里加入动画结束后要做的事
- }
- @Override
- public void onAnimationCancel(Animator animation) {
- // TODO Auto-generated method stub
- }
- });
如上所看到的,动画共同拥有四个状态。有时我们并不须要实现全部的方法,仅仅须要当中一个状态就能够了。那我们能够使用AnimatorListenerAdapter。它继承了AnimatorListener接口。
空实现了全部方法。
演示样例:
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- view.setY(startY);
- }
- });
安卓的属性动画大致就讲完了。
參考资料:
http://blog.csdn.net/lmj623565791/article/details/38067475
http://blog.csdn.net/singwhatiwanna/article/details/17841165
【Android】属性动画的更多相关文章
- Android属性动画
这几天看郭神的博客 Android属性动画完全解析(上),初识属性动画的基本用法之后,我自己突然想实现一种动画功能,就是我们在携程网.阿里旅行等等手机APP端买火车票的时候,看到有选择城市,那么就有出 ...
- 【转】android 属性动画之 ObjectAnimator
原文网址:http://blog.csdn.net/feiduclear_up/article/details/39255083 前面一篇博客讲解了 android 简单动画之 animtion,这里 ...
- Android属性动画之ValueAnimation
ValueAnimation是ObjectAnimation类的父类,经过前几天的介绍,相信大家对ObjectAnimation有了 一定的认识,今天就为大家最后介绍一下ValueAnimation, ...
- Android属性动画完全解析(下)
转载:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中我们学习了 ...
- Android属性动画完全解析(上),初识属性动画的基本用法
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系 ...
- Android属性动画完全解析(中)
转载:http://blog.csdn.net/guolin_blog/article/details/43536355 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是 ...
- Android属性动画完全解析(上)
Android属性动画完全解析(上) 转载:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷 ...
- Android 属性动画(Property Animation) 全然解析 (下)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38092093 上一篇Android 属性动画(Property Animatio ...
- Android 属性动画 源码解析 深入了解其内部实现
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42056859,本文出自:[张鸿洋的博客] 我参加了博客之星评选,如果你喜欢我的博 ...
- 用Android属性动画实现和演示迪士尼动画基本原则
本文将介绍在Android平台上实现和演示迪士尼动画基本准则. 项目开源,GitHub: https://github.com/vhow/animation 说明: 演示动画原则的想法源自 Anima ...
随机推荐
- Spring Boot特性(转)
摘要: 1. SpringApplication SpringApplication 类是启动 Spring Boot 应用的入口类,你可以创建一个包含 main() 方法的类,来运行 SpringA ...
- 数据切分——Mysql分区表的管理与维护
关于Mysql分区表的介绍可以参考: http://blog.csdn.net/jhq0113/article/details/44592865 关于Mysql分区表的创建可以参考: http://b ...
- Courses(最大匹配)
Courses Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- window.open 使用方法总结
[1.最基本的弹出窗口代码] <SCRIPT LANGUAGE="javascript"> <!-- window.open ('test.html') - ...
- STL之如何选择顺序容器
一.顺序容器的分类 顺序容器:vector向量.list链表.deque双端队列: 优先级最高的是vector向量,它的速度比较快,优点最多: 在程序设计中,容器可以切换: #include < ...
- UIButton上同时显示图片和文字的方法
copy from CPLASF_lixj http://blog.csdn.net/qijianli/article/details/8152726 项目中经常会遇到Button上同时显示图片和文 ...
- c++构造函数析构函数调用顺序
#include <iostream> using namespace std; class A { public: A () { cout<<"A 构造 " ...
- 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径
自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...
- SMTP邮件传输协议发送邮件和附件(转)
1. SMTP 常用命令简介 1). SMTP 常用命令 HELO/EHLO 向服务器标识用户身份 MAIL 初始化邮件传输 mail from: RCPT 标识单个的邮件接收人:常在MAIL ...
- struts2总结【转载】
1,struts2的form表单里面和url里面的传值以及Action所继承的父类都可以自动set属性注入action中,及继承的action中. 2,凡是url和form表单传值,在action方法 ...