Android Animation学习(三) ApiDemos解析:XML动画文件的使用
Android Animation学习(三) ApiDemos解析:XML动画文件的使用
可以用XML文件来定义Animation。
文件必须有一个唯一的根节点:
<set>, <objectAnimator>, or <valueAnimator>三者之一。
对应的Java类是:
- ValueAnimator - <animator>
- ObjectAnimator - <objectAnimator>
- AnimatorSet - <set>
<set>标签是可以嵌套的。
<set>标签的android:ordering属性规定了这个set中的动画的执行顺序。该属性值默认是together (default)。
比如:
<set android:ordering="sequentially" > <set>
<objectAnimator
android:duration="500"
android:propertyName="x"
android:valueTo="400"
android:valueType="intType" />
<objectAnimator
android:duration="500"
android:propertyName="y"
android:valueTo="300"
android:valueType="intType" />
</set> <objectAnimator
android:duration="500"
android:propertyName="alpha"
android:valueTo="1f" /> </set>
使用时:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(
myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();
为了区分Property animation和View animation的资源文件,从Android 3.1开始,Property animation的xml文件存在res/animator/目录下(View animation的存在res/anim/目录下), animator这个名是可选的。但是如果你想要使用Eclipse ADT plugin (ADT 11.0.0+)的布局编辑器,你就必须使用res/animator/目录,因为ADT只在该目录下寻找property animation的资源文件。
Api Demo相关代码:
代码结构和上一篇文章中的基本类似,也是各种小球的动画,只不过这次的动画效果都是从XML文件中读取的。
完整的项目见项目地址:https://github.com/mengdd/AnimationApiDemos.git
public class AnimationFromXmlActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置布局,布局xml中只包含了一个线性布局和一个Button
setContentView(R.layout.animation_basic); LinearLayout container = (LinearLayout) findViewById(R.id.container); // 将自定义的View加入到线性布局中
final MyAnimationView animView = new MyAnimationView(this);
container.addView(animView); // Button的点击事件即动画开始
Button starter = (Button) findViewById(R.id.startButton);
starter.setOnClickListener(new View.OnClickListener() { public void onClick(View v) {
animView.startAnimation();
}
});
} public class MyAnimationView extends View implements
ValueAnimator.AnimatorUpdateListener { private static final float BALL_SIZE = 100f; public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
Animator animation = null; public MyAnimationView(Context context) {
super(context);
addBall(50, 50);
addBall(200, 50);
addBall(350, 50);
addBall(500, 50, Color.GREEN);
} private void createAnimation() {
Context appContext = AnimationFromXmlActivity.this; if (animation == null) { // ========================================================
// 载入根节点为<objectAnimator>的xml资源文件,解析放进ObjectAnimator类对象
ObjectAnimator anim = (ObjectAnimator) AnimatorInflater
.loadAnimator(appContext, R.anim.object_animator);
anim.addUpdateListener(this);
anim.setTarget(balls.get(0)); // ========================================================
// 载入根节点为<animator>的xml资源文件,解析放进ValueAnimator类对象
ValueAnimator fader = (ValueAnimator) AnimatorInflater
.loadAnimator(appContext, R.anim.animator);
fader.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
// ValueAnimator动画需要在监听器中自己设置对象的属性值
// 这里改变的是alpha值
balls.get(1).setAlpha(
(Float) animation.getAnimatedValue());
}
}); // ========================================================
// 载入根节点为<set>的xml资源文件,解析放进AnimatorSet类对象
AnimatorSet seq = (AnimatorSet) AnimatorInflater.loadAnimator(
appContext, R.anim.animator_set);// x和y属性同时改变的动画集合
seq.setTarget(balls.get(2));
// 这里要注意:因为AnimatorSet没有设置AnimatorUpdateListener的方法,
// 所以如果其他动画没有设置AnimatorUpdateListener来进行View的invalidate()刷新,
// 这个AnimatorSet seq是不刷新的 // ========================================================
// 载入根节点为<objectAnimator>的xml资源文件,解析放进ObjectAnimator类对象
ObjectAnimator colorizer = (ObjectAnimator) AnimatorInflater
.loadAnimator(appContext, R.anim.color_animator);
colorizer.setTarget(balls.get(3));
colorizer.addUpdateListener(this); // ========================================================
// 总的AnimationSet,所有的动画同时播放
animation = new AnimatorSet();
((AnimatorSet) animation).playTogether(anim, fader, seq,
colorizer);
}
} public void startAnimation() {
createAnimation();
animation.start();
} private ShapeHolder createBall(float x, float y) {
OvalShape circle = new OvalShape();
circle.resize(BALL_SIZE, BALL_SIZE);
ShapeDrawable drawable = new ShapeDrawable(circle);
ShapeHolder shapeHolder = new ShapeHolder(drawable);
shapeHolder.setX(x);
shapeHolder.setY(y);
return shapeHolder;
} private void addBall(float x, float y, int color) {
ShapeHolder shapeHolder = createBall(x, y);
shapeHolder.setColor(color);
balls.add(shapeHolder);
} private void addBall(float x, float y) {
ShapeHolder shapeHolder = createBall(x, y);
int red = (int) (100 + Math.random() * 155);
int green = (int) (100 + Math.random() * 155);
int blue = (int) (100 + Math.random() * 155);
int color = 0xff000000 | red << 16 | green << 8 | blue;
Paint paint = shapeHolder.getShape().getPaint();
int darkColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue
/ 4;
RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f,
color, darkColor, Shader.TileMode.CLAMP);
paint.setShader(gradient);
balls.add(shapeHolder);
} @Override
protected void onDraw(Canvas canvas) {
// 遍历并绘制每一个球形对象
for (ShapeHolder ball : balls) {
// 这里是canvas.translate到一个地方,进行绘制,之后再translate回来
// 跟先save后restore的作用相同
canvas.translate(ball.getX(), ball.getY());
ball.getShape().draw(canvas);
canvas.translate(-ball.getX(), -ball.getY());
}
} public void onAnimationUpdate(ValueAnimator animation) { // 刷新View
invalidate(); // 因为第一个小球用的是ObjectAnimator,所以这里不必要自己设置属性值
// 如果是ValueAnimator就需要加上下面两行
// ShapeHolder ball = balls.get(0);
// ball.setY((Float) animation.getAnimatedValue());
}
}
}
相关动画:
资源文件:
第一个小球:下落,并且返回:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
第二个小球:消失(变为透明),然后再出现:
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:repeatCount="1"
android:repeatMode="reverse"/>
第三个小球:X轴与Y轴同时运动,并且返回:
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="x"
android:repeatCount="1"
android:repeatMode="reverse"/>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="400"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
</set>
第四个小球:颜色变化:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="#0f0"
android:valueTo="#00ffff"
android:propertyName="color"
android:repeatCount="1"
android:repeatMode="reverse"/>
参考资料
API Guides:Declaring Animations in XML
项目地址:https://github.com/mengdd/AnimationApiDemos.git
Android Animation学习(三) ApiDemos解析:XML动画文件的使用的更多相关文章
- Android开发学习---使用XmlPullParser解析xml文件
Android中解析XML的方式主要有三种:sax,dom和pull关于其内容可参考:http://blog.csdn.net/liuhe688/article/details/6415593 本文将 ...
- Android Animation学习 实现 IOS 滤镜退出动画
IOS的用户体验做的很好,其中一点很重要的地方就是动画效果. 最近在学习Android的Animation,简单实现了一个IOS相机滤镜退出的动画: 布局文件:activity_animation_d ...
- Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition
Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...
- Android Animation学习(四) ApiDemos解析:多属性动画
Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...
- Android Animation学习(二) ApiDemos解析:基本Animators使用
Android Animation学习(二) ApiDemos解析:基本Animatiors使用 Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.O ...
- Android Animation学习(二) ApiDemos解析:基本Animatiors使用
Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...
- Android Animation学习(一) Property Animation原理介绍和API简介
Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...
- Android Animation学习(六) View Animation介绍
Android Animation学习(六) View Animation介绍 View Animation View animation系统可以用来执行View上的Tween animation和F ...
- Android animation学习笔记之view/drawable animation
前一章中总结了android animation中property animation的知识和用法,这一章总结View animation和Drawable animation的有关知识: View ...
随机推荐
- jQuery邮箱自动补全代码
JScript 代码 复制 (function($){ $.fn.emailMatch= function(settings){ var defaultSettings = { emailTip: ...
- Android网格视图(GridView)
GridView的一些属性: 1.android:numColumns=”auto_fit” //GridView的列数设置为自动,也可以设置成2.3.4…… 2.android:columnWi ...
- Apache Kylin 部署之不完全指南
1. 引言 Apache Kylin(麒麟)是由eBay开源的分布式分析引擎,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据.底层存储用的是HBase,数据输入与cu ...
- SQL Server代理(1/12):配置和概况
SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. SQL Server代理是SQL Serv ...
- Fundamentals of MVC
Chapter 1 Fundamentals of MVC Microsoft's Web Development Platforms Understanding the past can b ...
- Guid算法与标识列(自动增长字段)在表中的应用
<<1>>int(bigint)+标识列(自动增长字段) 用标识列实现字段自增可以避免并发等问题.不需开发人员自己控制自增,用标识列的字段在Insert的时候不用指定主键的值. ...
- 为什么说Babel将推动JavaScript的发展
Babel是一个转换编译器,它能将ES6转换成可以在浏览器中运行的代码.Babel由来自澳大利亚的开发者Sebastian McKenzie创建.他的目标是使Babel可以处理ES6的所有新语法,并为 ...
- 比对两个同类型的List
比对两个List中的数据 1 List<Person> ListA= new List<Person>() { "}, "}, "}, " ...
- 纯灌水Linus主义
卖桃君重新整理了Linus的相关故事,在此摘选对自己有触动的内容. 关于生命的意义,李纳斯的解释是,有三件事具有生命的意义.它们是你生活当中所有事情的动机.第一是生存,第二是社会秩序,第三是娱乐.生活 ...
- linux下c程序的链接、装载和库(1)
读完<程序员的自我修养--链接.装载和库>相关章节,想来总结一下,若有错误,请指正,多谢. 1. 什么叫目标文件? 你的工程里有很多xxx.c这样的源文件,这些文件是文本文件,只有人能够认 ...