为了账号安全,请及时绑定邮箱和手机立即绑定

Android:展开/折叠动画

Android:展开/折叠动画

Qyouu 2019-06-24 09:59:46
Android:展开/折叠动画假设我有一个垂直线性Layout:[v1][v2]默认情况下,v1已经明显地=消失了。我想用扩展动画显示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做这件事有什么简单的方法吗?
查看完整描述

3 回答

?
温温酱

TA贡献1752条经验 获得超4个赞

我看到这个问题很受欢迎,所以我贴出了我的实际解决方案。主要的优点是您不需要知道扩展的高度才能应用动画,并且一旦视图被展开,如果内容发生变化,它就会适应高度。对我来说很管用。

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。


查看完整回答
反对 回复 2019-06-24
?
不负相思意

TA贡献1777条经验 获得超10个赞

我试图做一个我认为是非常相似的动画,并找到了一个优雅的解决方案。此代码假定您总是从0->h或h->0(h是最大高度)。这三个构造函数参数是view=要动画的视图(在我的示例中是webview)、Target tHL.8=视图的最大高度,以及down=指定方向的布尔值(true=展开、false=折叠)。

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


查看完整回答
反对 回复 2019-06-24
?
慕沐林林

TA贡献2016条经验 获得超9个赞

我今天在同一个问题上绊倒了,我想这个问题的真正解决办法是

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

您必须为所有最顶层的布局设置此属性,这些布局涉及到移位。如果您现在设置一个布局的可见性为消失,另一个将占用空间,因为正在消失的一个正在释放它。会有一个默认的动画,这是某种“淡出”,但我认为你可以改变这个-但最后一个我还没有测试,目前。


查看完整回答
反对 回复 2019-06-24
  • 3 回答
  • 0 关注
  • 1766 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信