1

I have a TextView inside a LinearLayout. My goal is to animate the TextView height change when its text changes and need more or less lines.

I split the work this way :

  1. Fade out the old text
  2. Animate the TextView new height (and the parent LinearLayout)
  3. Fade in the new text

The fade in / fade out part is easy, but I struggle for the height change animation.

Here's my simplified layout :

<LinearLayout
    android:id="@+id/fragment_tooltip_tooltip"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/tooltip_blue_bg"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/fragment_tooltip_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>

And here is what I tried :

    final int currentHeight = tvMessage.getHeight();

    tvMessage.setText(toTooltip.getMessage());

    tvMessage.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            TooltipFragment.this.tvMessage.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            final int newHeight = tvMessage.getHeight();

            ResizeAnimation resizeAnimation = new ResizeAnimation(tvMessage, tvMessage.getWidth(), tvMessage.getWidth(),
                    currentHeight, newHeight);
            resizeAnimation.setDuration(ANIM_DURATION_TRANSITION_TEXT_RESIZE);
            resizeAnimation.setInterpolator(new FastOutSlowInInterpolator());
            resizeAnimation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    // No-op
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    // Finally we show the new content
                    ...
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                    // No-op
                }
            });
            tvMessage.startAnimation(resizeAnimation);
        }
    });

The problem with this solution is that the tvMessage.setText(toTooltip.getMessage()); line used to measure the new height expand immediately the TextView and LinearLayout, then the animation resize the view to its previous size before applying the resize the animation, producing an ugly visual effect.

I believe a TextSwitcher will not animate the height change and so is not a solution, but I didn't tried it.

MickaelG
  • 326
  • 3
  • 16

2 Answers2

1

The solution for my problem was to use a dummy TextView and measure it with the new text instead of using the actual TextView. This way my TextView is not resized before the animation, and I just have to set the text at the end of the animation.

See this answer for details : Getting height of text view before rendering to layout

Community
  • 1
  • 1
MickaelG
  • 326
  • 3
  • 16
-1

You could use a handler that runs recursively for this, looks a bit cleaner too. So, for example, use this:

Call the function startTextAnimation()

Have a Handler animHandler = new Handler(); in your onCreate()

Then use this function:

public void startTextAnimation() {
   textView.setHeight(textView.getHeight() + 1);
   if (textView.getHeight < *whatheightyouwant*) {
       aninHandler.postDelayed(new Runnable() {
           @Override
           public void run() {
               startTextAnimation();
           }
       }, 200);
   }
}

You can set parameters accordingly, it should do the job. Hope it helps.

Steeno
  • 137
  • 5