5

I have a layout that animate as below

enter image description here

The txt_billion is shown dynamically, with android:animateLayoutChanges="true" (Layout code below).

Notice the Hundred is jumping (actually all are jumping, but the Hundred is just more obvious). How to prevent the text from jumping?

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:padding="8dp"
        android:background="#9f9"
        android:text="Hundreds" />
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:padding="8dp"
        android:background="#f9f"
        android:text="Thousands" />
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:padding="8dp"
        android:background="#0ff"
        android:text="Millions" />
    <TextView
        android:id="@+id/txt_billion"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:padding="8dp"
        android:visibility="gone"
        android:background="#ff0"
        android:text="Billions" />
</LinearLayout>

You could get the code from https://github.com/elye/issue_horizontal_layout_animate to test out

Elye
  • 53,639
  • 54
  • 212
  • 474

2 Answers2

1

Try to use Support Transitions instead animateLayoutChanges

First, remove android:animateLayoutChanges="true" from your XML file

After, add compile 'com.android.support:transition:25.4.0' to your app dependencies.

Then, add this line before change visibility (TransitionManager from android.support.transition package)

TransitionManager.beginDelayedTransition(parentOfAnimatedView);

For your code

public void clickMe(View view) {
        TransitionManager.beginDelayedTransition((ViewGroup) billionText.getParent());
        if (billionText.getVisibility() == View.GONE) {
            billionText.setVisibility(View.VISIBLE);
        } else {
            billionText.setVisibility(View.GONE);
        }
    }
princeparadoxes
  • 498
  • 3
  • 10
  • No, it doesn't solve the problem. The "Hundreds" still jump. Try on landscape mode, the jump is more obvious. – Elye Jun 20 '17 at 23:02
0

The problem is that animateLayoutChanges only affects subclasses of ViewGroup. TextView can't react to layout change animations, so the text jumps. There are two ways to fix it:

1) Wrap each TextView in a FrameLayout and put the weight on the FrameLayout. You'll also have to add android:animateLayoutChanges="true" to each, as well as calling getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING) on each FrameLayout. This is kind of gross layout-wise, but it will allow you to keep using the transition animations.

2) Use a ValueAnimator and animate the weight of the (dis)appearing item. The animation may be a little choppier since it needs to lay out the LinearLayout on each frame, but it should still be passable. You'd also have to solve for text reflowing on the disappearing item, maybe by animating it fading out first and then animating the weight change.

Jarett Millard
  • 5,802
  • 4
  • 41
  • 48