Search code examples
androidandroid-layoutviewandroid-animationandroid-wrap-content

How to scale the view to fit the content size in Android animation?


I am using CardView as a item of Recycler Adapter.

At first, all items will not show the whole content, (I cut it and put the '... ...' instead)
but after click it, the clicked item will scale its height to fit the content height. ( Here I set the text to the whole content and hope the card can scale to fit it )

looks like:

enter image description here

I know how to animate the height to the specific target height.. but in this case, I don't know how to measure the height needed to show the whole content, each item should have different target height.

How can I do it?


Solution

  • What you can do is ask the View to measure itself giving no constraint on its height. Please note the call to view.getWidth(), you can do that only after the View had been laid out, since you're calling it in onClick() it should be fine.

    int widthSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
    int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthSpec, heightSpec);
    int targetHeight = view.getMeasuredHeight();
    

    Assuming that your View is a TextView with these attributes set:

    android:layout_height="wrap_content"
    android:maxLines="1"
    android:ellipsize="end"
    

    the full example would be

    // this is the height measured with maxLines 1 and height
    // to wrap_content
    final int startHeight = view.getHeight();
    
    // you want to measure the TextView with all text lines
    view.setMaxLines(Integer.MAX_VALUE);
    
    int widthSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
    int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthSpec, heightSpec);
    
    // final height of the TextView
    int targetHeight = view.getMeasuredHeight();
    
    // this is the value that will be animated from 0% to 100%
    final int heightSpan = targetHeight-startHeight;
    
    // remove that wrap_content and set the starting point
    view.getLayoutParams().height = startHeight;
    view.setLayoutParams(view.getLayoutParams());
    
    Animation animation = new Animation(){
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            view.getLayoutParams().height = (int) (startHeight + heightSpan*interpolatedTime);
            view.setLayoutParams(view.getLayoutParams());
        }
    };
    
    animation.setDuration(1000);
    view.startAnimation(animation);