2.3插值器
AccelerateInterpolator:在动画开始的地方速率改变比较慢,然后开始加速
DecelerateInterpolator:减速插值器,在动画开始的一瞬间加速到最大值
LinearInterpolator:线性插值器,也称匀速插值器,速率保持恒定
BoubceInterpolator:弹跳插值器,模拟了控件自由落地后回弹的效果
AnticipateInterpolator:初始偏移插值器,表示在动画开始的时候向前偏移一段距离,然后应用动画,在旋转动画回先向反方向旋转,对于缩放和透明度渐类推。该插值器有一个构造函数(public AnticipateInterpolator(float tension)),tension表示张力,默认为2,张力越大,初始的偏移量越大,而且数越快。使用无参构造函数时,默认张力是2
OvershootInterpolator:结束偏移插值器,如上
AnticipateOvershootInterpolator:是AnticipateInterpolator和AnticipateInterpolator的结合体。
CycleInterpolator:循环插值器,表示动画循环播放特定的次数,速率沿正弦曲线改变。其构造函数传入的参数表示循环次数
属性动画
3.1 ValueAnimator的基本使用
3.1.1 概述
补间动画和逐帧动画统称为视图动画,这两个动画只能对派生自View的控件实例起作用,属性动画则是作用于控件属性的,他能单独改变控件某一个属性的值,比如颜色。所以属性动画是能够通过改变某一属性值来做动画的。而且补间动画并不能改变空间内部的属性值。(书p69有一个栗子)
3.1.2ValueAnimator的简单使用
这个动画针对的是值,不会对控件执行任何操作,我们可以给他设定从哪那个值到哪个值,通过监听这些值的渐变过程来改变自己
ValueAnimator 没有跟任何控件相关联,只对值进行动画运算,而不是针对控件,写个栗子解释一下
1
2
3ValueAnimator animator = ValueAnimator.ofInt(0, 400);
animator.setDuration(1000);
animator.start();- 属性动画的使用栗子,可以改变控件的属性的。给实例设置UpdateListener,然后在里面通过控件实例的layout()方法改变控件的属性值。需注意的layout()方法的改变是永久的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public class ValueAnimDemoActivity extends Activity {
private TextView tv;
private Button btn;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.translate_anim_activity);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
doAnimation();
}
});
tv.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(ValueAnimDemoActivity.this, "clicked me", Toast.LENGTH_SHORT).show();
}
});
}
private void doAnimation(){
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (Integer)animation.getAnimatedValue();
//如果前面调用的是ofFloat()方法,那么这里就转化为float型
tv.layout(curValue,curValue,curValue+tv.getWidth(),curValue+tv.getHeight());
}
});
animator.start();
}
}ValueAnimator的常用函数有ofInt()和ofFloat()。这两个函数的参数类型均是可变长参数,可传入任何的数量的值,但是传进去的数值越多,动画变化就越复杂。比如ofInt(2, 90, 45)就表示从数字2变化到90再变化到数字45。 通过getAnimatedValue()函数可以得到当前运动点的值,该函数返回的是一个object对象,转化为Integer型还是float型取决于调用的是ofInt()还是ofFloat()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/**
* 设置动画时长,单位是毫秒
*/
ValueAnimator setDuration(long duration);
/**
* 获取ValueAnimator在运动时当前运动点的值
*/
Object getAnimatedValue();
/**
* 开始动画
*/
void start();
/**
* 设置循环次数,设置为INFINITE表示无限循环
* 设置为零则表示不循环
*/
void setRepeatCount(int value);
/**
* 设置循环模式
* value的取值有RESTART 和 REVERSE
* RESTART表示正序重新开始
* REVERSE表示倒序重新开始
*/
void setRepeatMode(int value);
/**
* 取消动画
*/
void cancel();
3.1.3ValueAnimator监听器
其共有两个监听器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* 监听器一:监听动画过程中值的实时变化
*/
public static interface AnimatorUpdateListener{
void onAnimationUpdate(ValueAnimator animation);
}
/**
* 监听器二:监听动画变化时的四个状态
*/
public static interface AnimatorListener{
//当动画开始时
void onAnimationStart(Animator animation);
//当动画结束时
void onAnimationEnd(Animator animation);
//当动画取消时
void onAnimationCancel(Animtor animation);
//当动画重复时
void onAnimationRepeat(Animator animation);
}这里的监听器一主要用于监听过程中值的实时变化,监听器二主要监听Animation的4个状态.
对于移除监听器,提供全部移除和指定移除(需注意的一点是,移除listener后,并没有取消动画效果,所以动画会继续)
1
2
3
4
5
6
7
8
9
10
11
12
13/**
* 移除AnimatorUpdateListener
*/
void removeUpdateListener(AnimatorUpdateListener listener);
void removeAllUpdateListener();
/**
* 移除AnimatorListener
*/
void removeListener(AnimatorUpdateListener listener);
void removeAllListener();一些不常用的函数
1
2
3
4
5
6
7
8
9/**
* 延时多久开始,单位是毫秒
*/
public void setStartDelay(long startDelay)
/**
* 完全克隆一个ValueAnimator实例,包括它所有的设置以及所有对监听器代码的处理
*/
public ValueAnimator clone()
3.1.4 弹跳加载中效果
实现效果步骤需要考虑的点
- 控件应该派生自ImageView类,方便更改它的源文件类容
- 想要实现上下移动,可以先利用valueAnimator实时产生一个0~100的数据值,然后让当前的图片的位置实时向上移动valueAnimator的动态值得高度即可。
1 | public class LoadingImageView extends ImageView { |
3.2自定义插值器与Evaluator
3.2.1自定义插值器
插值器就是用来控制动画的区间如何被计算的
在ValueAnimator中使用插值器,直接调用ValueAnimator。setInterpolator(TimeInterpolator value)函数
系统的插值器的结构层次是
1
2
3
4
5
6
7
8
9
10
11Interpolator extends TimeInterpolator
//用LinearInterpolator举栗子
LinearInterpolator extends Interpolator
public interface TimeInterpolator{
//input的范围是0~1表示动画进度(动画进度)
//返回值表示的当前实际想要显示的进度(数值进度)
float getInterpolation(float input);
}用LinearInterpolator的核心代码做一个栗子
1
2
3
4
5
6
7public class LinearInterpolator implements Interpolator {
...
public float getInterpolation(float input){
return input;
}
}在这个栗子里面,直接返回的input,就是以当前的动画进度作为动画的数值进度,这样的话,动画的数值进度就与时间进度相同,所以它是匀速的。
3.2.2Evaluator
一、概述
ofInt(1, 400) (定义动画数值期间) -> 插值器(返回当前数值进度,如0.2) -> Evaluator(根据数值进度计算当前值) -> 监听器返回(在AnimatorUpdateListener中返回)
从定义动画的数值区间到在AnimatorUpdatel iscne得到当前动画所对应数值的整个过程的4个步骤的具体含义如下
ofInt(0,400); 表示指定动画的数值区间,从0运动 到400.
插值器:在动画开始后,通过插值器会返回当前动画进度所对应的数值进度,但这个数值进度是以小数表示的,如0.2。
Evaluator: 我们通过监听器拿到的是当前动画所对应的具体数值,而不是用小数表示的数值。那么必须有一个地方会根据当前的数值进度将其转换为对应的数值,这个地方就是Evaluator. Evaluator 用于将从插值器返回的数值进度转换成对应的数值。
监听器返回:我们通过在AnimatorUpdateListener 监听器中使用animation.getAnimatedValue()函数拿到Evaluator中返回的数值。
讲了这么多,Evaluator 其实就是- 个转换器,它能把小数进度转换成对应的数值位置。
二、各种Evaluator
在传入的时用的ofInt()还是ofFlaot()会对应不同的Evaluator,因为,需要返回整形合浮点型,如果不分开使用,则会出现,强转错误。所以ofInt()函数对应的就是IntEvaluator,ofFloat()类似。使用Evaluator时,使用animator.setEvaluator()函数来实现即可。在不主动提供的情况下,系统会默认提供的。
看一下IntEvaluator的内部时怎么实现的
1 | public class IntEvaluator implements TypeEvaluator<Integer> { |
fraction参数就是插值器中的返回值,表示当前动画的数值进度,以百分制的小数表示
startValue和endValue分别对应ofInt(int start, int end)函数中的start和end的数值。假设动画的ofInt(100, 400)数值进度为20%,则fraction为0.2,startValue为100,endValue为400
返回值就是当前数值进度所对应的具体数值,这个数值就是我们在AnimatoeUpdateListener监听器通过fetAnimatedValue()得到的数
当我们自定义Evaluator得时候,需要指定一个泛型,泛型事什么就由你用的ofInt()还是ofFloat()决定
1
2
3
4
5
6public class myIntEvaluator implements TypeEvaluator<Integer> {
p public Integer evaluate(float fraction, Integer startValue, Integer endValue{
//TODO...
}
}
结论: 既可以通过重写插值器改变数值进度来改变数值位置,也可以通过改变Evaluator中数值进度所对应的具体数值来改变数值位置
关于ArgbEvaluator
使用ArgbEvaluator:他是用来实现颜色值过渡转换的,使用方法与IntEvaluator和FloatEvaluator没什么差别
1
2
3
4
5
6
7
8
9
10
11ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);
animator.setDuration(3000);
animator.setEvaluator(new ArgbEvaluator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer curValue = (Integer) animation.getAnimatedValue();
tv.setBackgroundColor(curValue);
}
});
animatorstart();需要注意的是,这里必须使用ofInt()函数来定义颜色的取值范围,并且必须包括A、R、G、B四个值
关于ArgbEvaluator的实现原理
原理一共分为三个部分:
- 根据startValue求出A、R、G、B中各个色彩的初始值
- 根据endValue求出A、R、G、B中各个色彩的结束值
- 根据当前动画的百分比进度求出相对应的数值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
float startA = ((startInt >> 24) & 0xff) / 255.0f;
float startR = ((startInt >> 16) & 0xff) / 255.0f;
float startG = ((startInt >> 8) & 0xff) / 255.0f;
float startB = ( startInt & 0xff) / 255.0f;
int endInt = (Integer) endValue;
float endA = ((endInt >> 24) & 0xff) / 255.0f;
float endR = ((endInt >> 16) & 0xff) / 255.0f;
float endG = ((endInt >> 8) & 0xff) / 255.0f;
float endB = ( endInt & 0xff) / 255.0f;
// convert from sRGB to linear
startR = (float) Math.pow(startR, 2.2);
startG = (float) Math.pow(startG, 2.2);
startB = (float) Math.pow(startB, 2.2);
endR = (float) Math.pow(endR, 2.2);
endG = (float) Math.pow(endG, 2.2);
endB = (float) Math.pow(endB, 2.2);
// compute the interpolated color in linear space
float a = startA + fraction * (endA - startA);
float r = startR + fraction * (endR - startR);
float g = startG + fraction * (endG - startG);
float b = startB + fraction * (endB - startB);
// convert back to sRGB in the [0..255] range
a = a * 255.0f;
r = (float) Math.pow(r, 1.0 / 2.2) * 255.0f;
g = (float) Math.pow(g, 1.0 / 2.2) * 255.0f;
b = (float) Math.pow(b, 1.0 / 2.2) * 255.0f;
return Math.round(a) << 24 | Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b);
}
3.3ValueAnimator进阶 ——ofObject
3.3.1概述
1 | %第三问的求解 |