Android: Expand/collapse animation

后端 未结 30 2181
说谎
说谎 2020-11-22 05:01

Let\'s say I have a vertical linearLayout with :

[v1]
[v2]

By default v1 has visibily = GONE. I would like to show v1 with an expand animat

30条回答
  •  盖世英雄少女心
    2020-11-22 05:29

    I adapted the currently accepted answer by Tom Esterez, which worked but had a choppy and not very smooth animation. My solution basically replaces the Animation with a ValueAnimator, which can be fitted with an Interpolator of your choice to achieve various effects such as overshoot, bounce, accelerate, etc.

    This solution works great with views that have a dynamic height (i.e. using WRAP_CONTENT), as it first measures the actual required height and then animates to that height.

    public static void expand(final View v) {
        v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.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);
    
        ValueAnimator va = ValueAnimator.ofInt(1, targetHeight);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (Integer) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        va.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
            }
    
            @Override public void onAnimationStart(Animator animation) {}
            @Override public void onAnimationCancel(Animator animation) {}
            @Override public void onAnimationRepeat(Animator animation) {}
        });
        va.setDuration(300);
        va.setInterpolator(new OvershootInterpolator());
        va.start();
    }
    
    public static void collapse(final View v) {
        final int initialHeight = v.getMeasuredHeight();
    
        ValueAnimator va = ValueAnimator.ofInt(initialHeight, 0);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (Integer) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        va.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                v.setVisibility(View.GONE);
            }
    
            @Override public void onAnimationStart(Animator animation) {}
            @Override public void onAnimationCancel(Animator animation) {}
            @Override public void onAnimationRepeat(Animator animation) {}
        });
        va.setDuration(300);
        va.setInterpolator(new DecelerateInterpolator());
        va.start();
    }
    

    You then simply call expand( myView ); or collapse( myView );.

提交回复
热议问题