Android:展开/折叠动画

新手上路,请多包涵

假设我有一个垂直的线性布局:

 [v1]
[v2]

默认情况下,v1 有 visibily = GONE。我想用展开动画显示 v1 并同时按下 v2。

我试过这样的事情:

 Animation a = new Animation()
{
    int initialHeight;

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final int newHeight = (int)(initialHeight * interpolatedTime);
        v.getLayoutParams().height = newHeight;
        v.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        initialHeight = height;
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
};

但是有了这个解决方案,动画开始时我会眨眼。我认为这是由于 v1 在应用动画之前显示全尺寸造成的。

使用 javascript,这是 jQuery 的一行代码!有什么简单的方法可以用android做到这一点?

原文由 Tom Esterez 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

我看到这个问题变得很流行,所以我发布了我的实际解决方案。主要优点是您不必知道应用动画的展开高度,一旦视图展开,它会在内容发生变化时调整高度。这对我很有效。

 public static void expand(final View v) {
    int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
    int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
    final int targetHeight = v.getMeasuredHeight();

    // Older versions of android (pre API 21) cancel animations for views with a height of 0.
    v.getLayoutParams().height = 1;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? LayoutParams.WRAP_CONTENT
                    : (int)(targetHeight * interpolatedTime);
            v.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Expansion speed of 1dp/ms
    a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if(interpolatedTime == 1){
                v.setVisibility(View.GONE);
            }else{
                v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                v.requestLayout();
            }
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Collapse speed of 1dp/ms
    a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

正如@Jefferson 在评论中提到的那样,您可以通过更改动画的持续时间(以及速度)来获得更流畅的动画。目前已经设置为1dp/ms的速度

原文由 Tom Esterez 发布,翻译遵循 CC BY-SA 4.0 许可协议

您不需要实现动画,您可以将 android:animateLayoutChanges="true" 放在视图中,这样每当子视图布局发生变化时,它就会动画…

原文由 Ucdemir 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题