ApiDemos – BouncingBalls分析
2014-09-29 15:34
405 查看
ApiDemos – BouncingBalls分析
这个例子主要是介绍属性动画的使用的,关于属性动画的一些关键设定的值,我们在上一篇文章大致描述了一番。另外,在分析这个例子之前,我们需要知道属性动画的类层次关系,这样便于理解和使用。
它的层次关系如下:
![](https://img-blog.csdn.net/20140929153405811?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmd5aW5nbGk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图1 Animator类继承图
BouncingBalls类是一个普通的Activity,它添加了一个自定义的MyAnimationView到主界面中。我们先看这个MyAnimationView的构造函数是怎样的:
public class MyAnimationView extends View {
public MyAnimationView(Contextcontext) {
super(context);
// Animate background color
// Note that setting the background color will automatically invalidatethe
// view,so that the animated color, and the bouncing balls, get redisplayed on
// every frame of the animation.
ValueAnimator colorAnim =ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
}
MyAnimationView继承自View类,是个自定义View,它在构造函数里启动了一个属性动画,即colorAnim.start()。
这里面用到了一个ObjectAnimator,这个对象动画控制器可以直接作用于某个对象。还记得我们上节讲到的属性动画的几个关键步骤是哪些吗?设置属性动画,必然离不开这几个关键步骤,否则动画是不可能成功的。在本例中这个ObjectAnimator也同样做了这几步:
1) 选定对象(Object)+属性(Property):简称 O + P;
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
Object = this;
P = “backgroundColor”,这是View的背景色的属性值,也同时说明View中必然存在方法setP()以及getP(),即setBackgroundColor和getBackgroundColor;
2) 时长(Duration):简称D;
colorAnim.setDuration(3000);
D = 3000ms=3s
3) 时间插值(Time interpolation):简称T;
这里我们并没有指定T值,如果没有指定,那么T必须是线性插值,也就是说在某个时间点time,当前的属性值的相对变化位置是 T = time/D;
再看,下面的代码,
colorAnim.setEvaluator(new ArgbEvaluator());
那么这个ArgbEvaluator是干什么用的呢?这个ArgbEvaluator就是计算当前属性值的,也即当前View的背景色的哦。我们可以看看ArgbEvaluator()的实现啊:
/**
* This evaluator can be used to perform typeinterpolation between integer
* values that represent ARGB colors.
*/
public class ArgbEvaluatorimplements TypeEvaluator {
/**
* This function returns the calculated in-between value fora color
* given integers that represent the startand end values in the four
*bytes of the 32-bit int. Each channel is separately linearly interpolated
* and the resulting calculated values arerecombined into the return value.
*
* @param fraction The fraction fromthe starting to the ending values
* @param startValue A 32-bit int valuerepresenting colors in the
* separate bytes of the parameter
* @param endValue A 32-bit int valuerepresenting colors in the
* separate bytes of the parameter
* @return A value that is calculatedto be the linearly interpolated
* result, derived by separating the startand end values into separate
* color channels and interpolating eachone separately, recombining the
* resulting values in the same way.
*/
public Object evaluate(float fraction, ObjectstartValue, 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))));
}
}
从上面的代码可以看出,它的作用就是计算当前的颜色值。计算方法本质上讲就是:
当前背景色 = (BLUE – RED) * fraction = (BLUE– RED)* T = (BLUE – RED)*(time/D) = (BLUE – RED) * (time / 3000);
你也可以自定义自己的Evaluator,但是返回值必须是属性值的类型才行。
4) 反复次数(Repeat Count)和行为(Behavior):简称R&B;
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
R = ValueAnimator.INFINITE,无限变化哦
B = ValueAnimator.REVERSE,动画结束后再反向播放哦
5) 动画控制器(Animator):简称A;
A = ObjectAnimator;
6) 帧刷新率(Frame refresh delay):简称F;
没有设置哦,那么 F = 10ms,也就是说理论上讲10ms就会刷新一帧,即调用this.setBackgroundColor一次哦。
上面6个步骤就是一个属性动画的完整步骤。
当前了这个动画还可以通过XML文件来实现,这个我们最后再讲吧。
在这个BouncingBalls界面,手指滑动会产生N多个运动的小球哦。我们来看看MyAnimationView的onTouchEvent事件:
@Override
public boolean onTouchEvent(MotionEventevent) {
if (event.getAction() != MotionEvent.ACTION_DOWN &&
event.getAction() !=MotionEvent.ACTION_MOVE) {
return false;
}
ShapeHolder newBall =addBall(event.getX(), event.getY());
// Bouncing animation with squash and stretch
float startY = newBall.getY();
float endY = getHeight() - 50f;
float h = (float)getHeight();
float eventY = event.getY();
int duration = (int)(500 * ((h - eventY)/h));
ValueAnimator bounceAnim =ObjectAnimator.ofFloat(newBall, "y", startY, endY);
bounceAnim.setDuration(duration);
bounceAnim.setInterpolator(new AccelerateInterpolator());
从上面的代码得知,在MOVE事件的时候,创建一个ShapeHolder类型的对象,然后在这个对象上创建它的”y”属性的动画,当然了这个ShapeHolder是自定义的对象,具体是什么大家自己看吧,但是可以肯定的是这个对象一定有一个getY和setY方法。比较新鲜的是设定了时间插值对象:
bounceAnim.setInterpolator(new AccelerateInterpolator());
这个AccelerateInterpolator就是我们上面提到的T值。它的实现如下:
/**
* An interpolator where the rate of changestarts out slowly and
* and then accelerates.
*
*/
public class AccelerateInterpolator implements Interpolator {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
/**
* Constructor
*
* @param factor Degree to which theanimation should be eased. Seting
* factor to 1.0f produces a y=x^2 parabola. Increasing factor above
* 1.0f exaggerates the ease-in effect (i.e.,it starts even
* slower and ends evens faster)
*/
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Contextcontext, AttributeSet attrs) {
TypedArray a =
context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.AccelerateInterpolator);
mFactor =a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor,1.0f);
mDoubleFactor = 2 * mFactor;
a.recycle();
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return
b7a9
input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
上面最主要的方法是getInterpolation()这个方法,这个值返回当前属性值的T值,其中参数input其实就是线性变化百分比,如果直接把input(0.0<= input <=1.0)返回的话,那么属性值的变化是线性的,但是本类顾名思义是一个加速插值类型,所以返回的值类型是input*input,这样看起来就会有加速的功能哦。
onTouchEvent()中有一段代码是这样的:
// Sequence the twoanimations to play one after the other
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
// Start the animation
animatorSet.start();
AnimatorSet是干什么用的,原来这个直译就是动画控制器组合,说白了,可以让N个Animator同时动画,或者一前一后等。把所有的动画集中起来控制哦。
好了,上面就是这个例子的主要知识点了哦。
下面,我们看看如何在XML中设置属性动画的呢。属性动画的XML文件位置应当放在目录/res/animator/下面,我们以更改背景色为例,创建一个myanimationview_background_change.xml:
<?xml version="1.0"encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="#FFFF8080"
android:valueTo="#FF8080FF"
android:repeatCount="-1"
android:repeatMode="reverse"
></objectAnimator>
</set>
修改MyAnimationView的构造函数:
public MyAnimationView(Context context) {
super(context);
// Animate background color
// Note that setting the background color will automatically invalidatethe
// view, so that the animated color, and the bouncing balls, getredisplayed on
// every frame of the animation.
/*ValueAnimator colorAnim = ObjectAnimator.ofInt(this,"backgroundColor", RED, BLUE);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(newArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();*/
AnimatorSet colorAnimSet =(AnimatorSet)AnimatorInflater.loadAnimator(context, R.animator.myanimationview_background_change);
ObjectAnimator colorAnim =(ObjectAnimator)colorAnimSet.getChildAnimations().get(0);
colorAnim.setTarget(this);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnimSet.start();
}
请下载APIDemos源码
这个例子主要是介绍属性动画的使用的,关于属性动画的一些关键设定的值,我们在上一篇文章大致描述了一番。另外,在分析这个例子之前,我们需要知道属性动画的类层次关系,这样便于理解和使用。
它的层次关系如下:
图1 Animator类继承图
BouncingBalls类是一个普通的Activity,它添加了一个自定义的MyAnimationView到主界面中。我们先看这个MyAnimationView的构造函数是怎样的:
public class MyAnimationView extends View {
public MyAnimationView(Contextcontext) {
super(context);
// Animate background color
// Note that setting the background color will automatically invalidatethe
// view,so that the animated color, and the bouncing balls, get redisplayed on
// every frame of the animation.
ValueAnimator colorAnim =ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
}
MyAnimationView继承自View类,是个自定义View,它在构造函数里启动了一个属性动画,即colorAnim.start()。
这里面用到了一个ObjectAnimator,这个对象动画控制器可以直接作用于某个对象。还记得我们上节讲到的属性动画的几个关键步骤是哪些吗?设置属性动画,必然离不开这几个关键步骤,否则动画是不可能成功的。在本例中这个ObjectAnimator也同样做了这几步:
1) 选定对象(Object)+属性(Property):简称 O + P;
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
Object = this;
P = “backgroundColor”,这是View的背景色的属性值,也同时说明View中必然存在方法setP()以及getP(),即setBackgroundColor和getBackgroundColor;
2) 时长(Duration):简称D;
colorAnim.setDuration(3000);
D = 3000ms=3s
3) 时间插值(Time interpolation):简称T;
这里我们并没有指定T值,如果没有指定,那么T必须是线性插值,也就是说在某个时间点time,当前的属性值的相对变化位置是 T = time/D;
再看,下面的代码,
colorAnim.setEvaluator(new ArgbEvaluator());
那么这个ArgbEvaluator是干什么用的呢?这个ArgbEvaluator就是计算当前属性值的,也即当前View的背景色的哦。我们可以看看ArgbEvaluator()的实现啊:
/**
* This evaluator can be used to perform typeinterpolation between integer
* values that represent ARGB colors.
*/
public class ArgbEvaluatorimplements TypeEvaluator {
/**
* This function returns the calculated in-between value fora color
* given integers that represent the startand end values in the four
*bytes of the 32-bit int. Each channel is separately linearly interpolated
* and the resulting calculated values arerecombined into the return value.
*
* @param fraction The fraction fromthe starting to the ending values
* @param startValue A 32-bit int valuerepresenting colors in the
* separate bytes of the parameter
* @param endValue A 32-bit int valuerepresenting colors in the
* separate bytes of the parameter
* @return A value that is calculatedto be the linearly interpolated
* result, derived by separating the startand end values into separate
* color channels and interpolating eachone separately, recombining the
* resulting values in the same way.
*/
public Object evaluate(float fraction, ObjectstartValue, 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))));
}
}
从上面的代码可以看出,它的作用就是计算当前的颜色值。计算方法本质上讲就是:
当前背景色 = (BLUE – RED) * fraction = (BLUE– RED)* T = (BLUE – RED)*(time/D) = (BLUE – RED) * (time / 3000);
你也可以自定义自己的Evaluator,但是返回值必须是属性值的类型才行。
4) 反复次数(Repeat Count)和行为(Behavior):简称R&B;
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
R = ValueAnimator.INFINITE,无限变化哦
B = ValueAnimator.REVERSE,动画结束后再反向播放哦
5) 动画控制器(Animator):简称A;
A = ObjectAnimator;
6) 帧刷新率(Frame refresh delay):简称F;
没有设置哦,那么 F = 10ms,也就是说理论上讲10ms就会刷新一帧,即调用this.setBackgroundColor一次哦。
上面6个步骤就是一个属性动画的完整步骤。
当前了这个动画还可以通过XML文件来实现,这个我们最后再讲吧。
在这个BouncingBalls界面,手指滑动会产生N多个运动的小球哦。我们来看看MyAnimationView的onTouchEvent事件:
@Override
public boolean onTouchEvent(MotionEventevent) {
if (event.getAction() != MotionEvent.ACTION_DOWN &&
event.getAction() !=MotionEvent.ACTION_MOVE) {
return false;
}
ShapeHolder newBall =addBall(event.getX(), event.getY());
// Bouncing animation with squash and stretch
float startY = newBall.getY();
float endY = getHeight() - 50f;
float h = (float)getHeight();
float eventY = event.getY();
int duration = (int)(500 * ((h - eventY)/h));
ValueAnimator bounceAnim =ObjectAnimator.ofFloat(newBall, "y", startY, endY);
bounceAnim.setDuration(duration);
bounceAnim.setInterpolator(new AccelerateInterpolator());
从上面的代码得知,在MOVE事件的时候,创建一个ShapeHolder类型的对象,然后在这个对象上创建它的”y”属性的动画,当然了这个ShapeHolder是自定义的对象,具体是什么大家自己看吧,但是可以肯定的是这个对象一定有一个getY和setY方法。比较新鲜的是设定了时间插值对象:
bounceAnim.setInterpolator(new AccelerateInterpolator());
这个AccelerateInterpolator就是我们上面提到的T值。它的实现如下:
/**
* An interpolator where the rate of changestarts out slowly and
* and then accelerates.
*
*/
public class AccelerateInterpolator implements Interpolator {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
/**
* Constructor
*
* @param factor Degree to which theanimation should be eased. Seting
* factor to 1.0f produces a y=x^2 parabola. Increasing factor above
* 1.0f exaggerates the ease-in effect (i.e.,it starts even
* slower and ends evens faster)
*/
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Contextcontext, AttributeSet attrs) {
TypedArray a =
context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.AccelerateInterpolator);
mFactor =a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor,1.0f);
mDoubleFactor = 2 * mFactor;
a.recycle();
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return
b7a9
input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
上面最主要的方法是getInterpolation()这个方法,这个值返回当前属性值的T值,其中参数input其实就是线性变化百分比,如果直接把input(0.0<= input <=1.0)返回的话,那么属性值的变化是线性的,但是本类顾名思义是一个加速插值类型,所以返回的值类型是input*input,这样看起来就会有加速的功能哦。
onTouchEvent()中有一段代码是这样的:
// Sequence the twoanimations to play one after the other
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
// Start the animation
animatorSet.start();
AnimatorSet是干什么用的,原来这个直译就是动画控制器组合,说白了,可以让N个Animator同时动画,或者一前一后等。把所有的动画集中起来控制哦。
好了,上面就是这个例子的主要知识点了哦。
下面,我们看看如何在XML中设置属性动画的呢。属性动画的XML文件位置应当放在目录/res/animator/下面,我们以更改背景色为例,创建一个myanimationview_background_change.xml:
<?xml version="1.0"encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="#FFFF8080"
android:valueTo="#FF8080FF"
android:repeatCount="-1"
android:repeatMode="reverse"
></objectAnimator>
</set>
修改MyAnimationView的构造函数:
public MyAnimationView(Context context) {
super(context);
// Animate background color
// Note that setting the background color will automatically invalidatethe
// view, so that the animated color, and the bouncing balls, getredisplayed on
// every frame of the animation.
/*ValueAnimator colorAnim = ObjectAnimator.ofInt(this,"backgroundColor", RED, BLUE);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(newArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();*/
AnimatorSet colorAnimSet =(AnimatorSet)AnimatorInflater.loadAnimator(context, R.animator.myanimationview_background_change);
ObjectAnimator colorAnim =(ObjectAnimator)colorAnimSet.getChildAnimations().get(0);
colorAnim.setTarget(this);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnimSet.start();
}
请下载APIDemos源码
相关文章推荐
- [ApiDemos] AlertDialog 使用和源码分析
- Android SDK Simple 例程分析之 ApiDemos 的 ApiDemos.java 分析
- SDK Simples 之 ApiDemos 一 启动分析
- ApiDemos--FragmenAlertDialog的例子分析
- 狂刷Android范例之5:ApiDemos主程序框架分析
- ApiDemos--FragmentArguments的例子分析
- ApiDemos—FragmentCustomAnimations分析
- C++的不足之处讨论系列(二)-- 全局分析
- [导入]Web搜索引擎设计和实现分析
- 如何写系统分析书
- "陷阱"技术探秘----动态汉化Windows技术的分析
- Java 编程技术中汉字问题的分析及解决
- php4.0.0远程溢出源代码分析与测试程序
- Java 编程技术中汉字问题的分析及解决
- "陷阱"技术探秘 ----动态汉化Windows技术的分析
- 关于Basic程序解释器及编译原理的简单化(1)--词法分析和代数式求值
- 关于Basic程序解释器及编译原理的简单化(1)---Basic器的语法分析及主要代码
- "欢乐时光"代码分析
- Linux开机过程的分析
- LILO使用指南 MBR 根分区 lilo.conf 出错分析 忘记密码