使用ValueAnimator创建LinearLayout容器高度的动画效果

24

我有一个LinearLayout,用作一些按钮和文本视图的容器,我想要动画化其高度,以便在用户按下“显示”按钮时给出布局向下滑动的印象。

我已经在xml中将LinearLayout设置为layout_height="0dp" 和 visibility="gone"。然后我希望将其设置为可见,并需要适当的高度来包裹内容。目前,我甚至无法对其进行任何动画处理,更不用说自适应内容高度了。

这是我的动画方法:

private void toggle(final LinearLayout v) {
    v.setVisibility(View.VISIBLE);
    ValueAnimator va = ValueAnimator.ofInt(0, 300);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            v.getLayoutParams().height = value.intValue();
            v.invalidate();

        }
    });

    va.start();
}
也许问题出在我设置LinearLayout高度的方式上?还是我误解了ValueAnimator的功能?我查看了Chet Haase的博客文章,但它们中没有包含任何特定的高度动画示例。我也没有找到使用3.0+ API处理高度动画的好例子。希望能得到一些帮助,谢谢!

为什么不直接使用布局动画呢? - Aleks G
坦白地说,我不知道如何使用它,而且我想既然我只针对较新版本的API,使用更新的类会更简单...如果您知道如何使用LayoutAnimation,请随时将其发布为更好的解决方案,我会继续研究如何使用它。 :) - span
有无使invalidate失效的原因? - portfoliobuilder
1个回答

61

阅读了这篇博客文章:http://tech.chitgoks.com/2011/10/29/android-animation-to-expand-collapse-view-its-children/,我发现我不应该使用view.invalidate()来重新绘制布局。而是应该使用view.requestLayout()

因此代码变成了这样:

ValueAnimator va = ValueAnimator.ofInt(0, height);
    va.setDuration(700);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            v.getLayoutParams().height = value.intValue();
            v.requestLayout();
        }
    });

我只想补充一下如何获取LinearLayout的高度,以使动画更加动态。要获取高度,所有视图都需要先绘制出来。因此,我们必须监听一个事件,告诉我们绘制完成了。可以从onResume()方法中执行此操作(请注意,在我的xml中,我声明了容器的高度为wrap_content,并且它也是可见的,因为我想在测量后隐藏它):

@Override
    public void onResume() {
        super.onResume();
        final ViewTreeObserver vto = filterContainer.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                height = filterContainer.getHeight();
                filterContainer.setVisibility(View.GONE);
                filterContainer.getLayoutParams().height = 0;
                filterContainer.requestLayout();
                ViewTreeObserver obs = filterContainer.getViewTreeObserver();
                obs.removeGlobalOnLayoutListener(this);
            }
        });
    }

3
这帮助我理解如何使用getAnimatedValue。谢谢。 - speedynomads
值动画器的更好工作是它将在指定持续时间内取开始点和结束点之间的中间值,我们可以通过该中间值更新布局高度,直到达到目标高度。动画也非常流畅。谢谢。 - Jay Shah
非常感谢!答案的第二部分对我帮助很大! - Victor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接