转载请注明出处
作者:AboutJoke ( http://blog.csdn.net/u013200308 )
原文链接:http://blog.csdn.net/u013200308/article/details/51250217
在介绍之前,先让我们来看一个图:
那么如图所示的效果是如何实现的呢?这里就需要用到我们今天的主角———ValueAnimator。
首先让我们来看一下官方的介绍:
这个类提供了一个用于计算动画值并将其设置为目标对象的动画的简单时序引擎。
默认情况下,ValueAnimator采用非线性时域插值,通过AccelerateDecelerateInterpolator类,加速和减速的动画。这种行为可以通过调用setinterpolator改变(timeinterpolator)。
从上面的内容我们可以看出来ValueAnimator并不能算作是动画,因为它是通过一系列复杂的计算,使一个值开始非线性变化到另一个值。让我们先通过一个demo来了解一下:
//参数 int... values 可以传入任意个数,如0,25,50
ValueAnimator animator=ValueAnimator.ofInt(0,25,50);// 0 -25 -50
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value=(Integer) animation.getAnimatedValue(); // 当前时间点变化后的值
System.out.println(value);
}
});
animator.setDuration(300);
animator.start();
结果:
从logcat中我们可以很清楚的看出来,进行了0到50的变化,变化的值在随机的增加。了解完毕,那就让我们来实现文章开始的图例。
首先我们分析一下,要实现图例的动画效果,只要让该控件的高度进行ValueAnimator的变化即可。那么,我们首先就需要获得该控件的高度。很多同学肯定会说用getMeasureHeight()就行了啊,在这里却不能这样做。为什么呢?因为该控件的高度是在变化的,所以我们就必须要获取它的实际高度,那我们就需要对该控件重新测量高度:
private int getMeasureHeight() {
//获取控件的宽度
int width = safe_content.getMeasuredWidth();
//让控件的高度为内容包裹
safe_content.getLayoutParams().height = LinearLayout.LayoutParams.WRAP_CONTENT;
//测量控件的宽度 参数1:大小 参数2:测量控件的mode
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
//因控件高度会发生变化 故高度最大为1000,以实际为准
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST);
safe_content.measure(widthMeasureSpec, heightMeasureSpec);
return safe_content.getMeasuredHeight();
}
这里用到了一个makeMeasureSpec()方法,该方法用来制定测量规则。参数1是大小,即待测量控件的宽度或高度;参数2为测量控件的mode,有三种模式:
- AT_MOST:控件的大小最大可以达到你想要的值;
- EXACTLY:控件将会被赋予你给给的值;
- UNSPECIFIED:没有约束,它可以是你想要的任何值;
在当前的例子中,控件的宽度是精确的值,因此我们使用EXACTLY。控件的高度是不确定的,因此我们先让控件内容包裹,然后再传入一个较大的值,交由系统去测量,这样就可以得到控件的高度。
// 值动画
ValueAnimator animator = ValueAnimator.ofInt(startHeight, targetHeight);
final LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) safe_content.getLayoutParams();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { // 监听值的变化
@Override
public void onAnimationUpdate(ValueAnimator animator) {
int value = (Integer) animator.getAnimatedValue();// 运行当前时间点的一个值
layoutParams.height = value;
safe_content.setLayoutParams(layoutParams);// 刷新界面
}
});
执行ValueAnimator,将得到的变化的高度值设置给控件的高度,即可实现收起和展开的动画效果。这样我们就完成了图例的第一个动画,而第二个动画和第一个又有所不同,它是从一个固定的高度开始变化,所以我们在测量的时候又要做一些变化,至于如何变化有兴趣的同学可以去自己尝试一下,完整的代码将在文章末尾给出。
Demo下载地址:
https://github.com/AboutJoke/ValueAnimator
后续我还会继续和大家分享关于Android的相关知识和技巧,欢迎大家关注,我们一起学习和进步。