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?


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

public static void expand(final View v) {
    v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    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;
        }
    };

    // 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;
        }
    };

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

我试图做我认为是非常相似的动画,并找到了一个优雅的解决方案。 这段代码假定你总是从0-> h或h-> 0(h是最大高度)。 这三个构造函数参数是view =动画视图(在我的情况下是webview),targetHeight =视图的最大高度,down =指定方向的布尔值(true = expanded,false = collapsing)。

public class DropDownAnim extends Animation {
    private final int targetHeight;
    private final View view;
    private final boolean down;

    public DropDownAnim(View view, int targetHeight, boolean down) {
        this.view = view;
        this.targetHeight = targetHeight;
        this.down = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down) {
            newHeight = (int) (targetHeight * interpolatedTime);
        } else {
            newHeight = (int) (targetHeight * (1 - interpolatedTime));
        }
        view.getLayoutParams().height = newHeight;
        view.requestLayout();
    }

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

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

我今天偶然发现了同样的问题,我猜这个问题的真正解决方案是这样的

<LinearLayout android:id="@+id/container"
android:animateLayoutChanges="true"
...
 />

您将不得不为该变化中涉及的所有最高布局设置此属性。 如果您现在将一个布局的可见性设置为GONE,另一个布局将消失的空间释放它。 将有一种默认动画是某种“淡出”,但我认为你可以改变这一点 - 但现在我还没有测试过最后一个。

链接地址: http://www.djcxy.com/p/84227.html

上一篇: Android: Expand/collapse animation

下一篇: Restrict Firebase users by email