Android: Expand/collapse animation

后端 未结 30 2177
说谎
说谎 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:31

    For Smooth animation please use Handler with run method.....And Enjoy Expand /Collapse animation

        class AnimUtils{
    
                     public void expand(final View v) {
                      int ANIMATION_DURATION=500;//in milisecond
            v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
            final int targtetHeight = v.getMeasuredHeight();
    
            v.getLayoutParams().height = 0;
            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)(targtetHeight * interpolatedTime);
                    v.requestLayout();
                }
    
                @Override
                public boolean willChangeBounds() {
                    return true;
                }
            };
    
            // 1dp/ms
            a.setDuration(ANIMATION_DURATION);
    
          // a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
            v.startAnimation(a);
        }
    
    
    
        public 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(ANIMATION_DURATION);
           // a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
            v.startAnimation(a);
        }
    }
    

    And Call using this code:

           private void setAnimationOnView(final View inactive ) {
        //I am applying expand and collapse on this TextView ...You can use your view 
    
        //for expand animation
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
    
                new AnimationUtililty().expand(inactive);
    
            }
        }, 1000);
    
    
        //For collapse
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
    
                new AnimationUtililty().collapse(inactive);
                //inactive.setVisibility(View.GONE);
    
            }
        }, 8000);
    
    }
    

    Other solution is:

                   public void expandOrCollapse(final View v,String exp_or_colpse) {
        TranslateAnimation anim = null;
        if(exp_or_colpse.equals("expand"))
        {
            anim = new TranslateAnimation(0.0f, 0.0f, -v.getHeight(), 0.0f);
            v.setVisibility(View.VISIBLE);  
        }
        else{
            anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, -v.getHeight());
            AnimationListener collapselistener= new AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                v.setVisibility(View.GONE);
                }
            };
    
            anim.setAnimationListener(collapselistener);
        }
    
         // To Collapse
            //
    
        anim.setDuration(300);
        anim.setInterpolator(new AccelerateInterpolator(0.5f));
        v.startAnimation(anim);
    }
    
    0 讨论(0)
  • 2020-11-22 05:31

    Best solution for expand/collapse view's:

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            View view = buttonView.getId() == R.id.tb_search ? fSearch : layoutSettings;
            transform(view, 200, isChecked
                ? ViewGroup.LayoutParams.WRAP_CONTENT
                : 0);
        }
    
        public static void transform(final View v, int duration, int targetHeight) {
            int prevHeight  = v.getHeight();
            v.setVisibility(View.VISIBLE);
            ValueAnimator animator;
            if (targetHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
                v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                animator = ValueAnimator.ofInt(prevHeight, v.getMeasuredHeight());
            } else {
                animator = ValueAnimator.ofInt(prevHeight, targetHeight);
            }
            animator.addUpdateListener(animation -> {
                v.getLayoutParams().height = (animation.getAnimatedFraction() == 1.0f)
                        ? targetHeight
                        : (int) animation.getAnimatedValue();
                v.requestLayout();
            });
            animator.setInterpolator(new LinearInterpolator());
            animator.setDuration(duration);
            animator.start();
        }
    
    0 讨论(0)
  • 2020-11-22 05:33
    public static void expand(final View v, int duration, int targetHeight) {
            v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            v.getLayoutParams().height = 0;
            v.setVisibility(View.VISIBLE);
            ValueAnimator valueAnimator = ValueAnimator.ofInt(0, targetHeight);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    v.getLayoutParams().height = (int) animation.getAnimatedValue();
                    v.requestLayout();
                }
            });
            valueAnimator.setInterpolator(new DecelerateInterpolator());
            valueAnimator.setDuration(duration);
            valueAnimator.start();
        }
    public static void collapse(final View v, int duration, int targetHeight) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, targetHeight);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }
    
    0 讨论(0)
  • 2020-11-22 05:34

    I see that this question became popular so I post my actual solution. The main advantage is that you don't have to know the expanded height to apply the animation and once the view is expanded, it adapts height if content changes. It works great for me.

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

    As mentioned by @Jefferson in the comments, you can obtain a smoother animation by changing the duration (and hence the speed) of the animation. Currently, it has been set at a speed of 1dp/ms

    0 讨论(0)
  • 2020-11-22 05:34

    combined solutions from @Tom Esterez and @Geraldo Neto

    public static void expandOrCollapseView(View v,boolean expand){
    
        if(expand){
            v.measure(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
            final int targetHeight = v.getMeasuredHeight();
            v.getLayoutParams().height = 0;
            v.setVisibility(View.VISIBLE);
            ValueAnimator valueAnimator = ValueAnimator.ofInt(targetHeight);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    v.getLayoutParams().height = (int) animation.getAnimatedValue();
                    v.requestLayout();
                }
            });
            valueAnimator.setInterpolator(new DecelerateInterpolator());
            valueAnimator.setDuration(500);
            valueAnimator.start();
        }
        else
        {
            final int initialHeight = v.getMeasuredHeight();
            ValueAnimator valueAnimator = ValueAnimator.ofInt(initialHeight,0);
            valueAnimator.setInterpolator(new DecelerateInterpolator());
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    v.getLayoutParams().height = (int) animation.getAnimatedValue();
                    v.requestLayout();
                    if((int)animation.getAnimatedValue() == 0)
                        v.setVisibility(View.GONE);
                }
            });
            valueAnimator.setInterpolator(new DecelerateInterpolator());
            valueAnimator.setDuration(500);
            valueAnimator.start();
        }
    }
    
    //sample usage
    expandOrCollapseView((Your ViewGroup),(Your ViewGroup).getVisibility()!=View.VISIBLE);
    
    0 讨论(0)
  • 2020-11-22 05:35

    If you don't want to expand or collapse all the way - here is a simple HeightAnimation -

    import android.view.View;
    import android.view.animation.Animation;
    import android.view.animation.Transformation;
    
    public class HeightAnimation extends Animation {
        protected final int originalHeight;
        protected final View view;
        protected float perValue;
    
        public HeightAnimation(View view, int fromHeight, int toHeight) {
            this.view = view;
            this.originalHeight = fromHeight;
            this.perValue = (toHeight - fromHeight);
        }
    
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            view.getLayoutParams().height = (int) (originalHeight + perValue * interpolatedTime);
            view.requestLayout();
        }
    
        @Override
        public boolean willChangeBounds() {
            return true;
        }
    }
    

    Usage:

    HeightAnimation heightAnim = new HeightAnimation(view, view.getHeight(), viewPager.getHeight() - otherView.getHeight());
    heightAnim.setDuration(1000);
    view.startAnimation(heightAnim);
    
    0 讨论(0)
提交回复
热议问题