The Challenge of Arranging Horizontal TextViews

This problem seems simple from the sound of it, but it’s a has it’s tricky bits that might surprise you.

The Requirements

Your designer came up to you, asking you to create 4 texts, i.e. Good, Intermediate, Bad and Worst horizontally. Sounds really easy.

First thing in mind is to use LinearLayout and with equal weight for each, so they are arranged symmetrically as shown below.

Then came a new requirement. We also want the ability to dynamically remove and add the Worst text per needed. Smooth animation is needed when the change happens. Ya, animateLayoutChanges came in mind. Trivia.

The codes as below

<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:animateLayoutChanges="true">

<TextView
style="@style/default_text_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/text_good" />

<!-- ... repeat with all Text .. -->

</LinearLayout>

The Problem

The image looks great as there are lines at each boundary. However in actual design, we don’t want those lines.

Checkout how it looks like without the line below. The spacing is just wrong!

Okay, let’s live with that for now. Try to work on the animation… Let see how it looks like using animateLayoutChanges.

Notice the Good? It is NOT Good! It jumps when animating. It is not smooth. It’s simply because the animateLayoutChanges by default will first calculate the new TextView width, realign the text, then only animate the boundaries. Bumper, a limitation of default animateLayoutChanges.

From the thought of it, the issue at the first glance is tricky. It’s actually unsolvable if we still want to stick with the symmetrical (equal weight) approach where all the TextViews is equally width.

So, to solve the problem, what we actually need is not the same width TextViews. But instead the same spacing between the TextViews. But how could we achieve that? Do we perform calculation and animation LayoutParam padding parameters for all the TextViews?

The Solution

After some exploration, apparently there’s a simpler scalable solution. All still in XML.

What we need is just make all our TextViews with width Wrap-Content, and use equal weight Space slot in between them (yes, Space is actually a View wizard type that is lightweight, with the purpose of producing space, yeah).

The codes as below

<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:animateLayoutChanges="true">

<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>

<TextView
style="@style/default_text_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_good" />

<!-- ... repeat with all Space/Text .. -->

</LinearLayout>

Check out how it looks below. Equally spaced out. Neat isn’t it?

With the boundary on, you could see the spacing more clearly. Not symmetrical, but it looks better when the boundaries is removed.

How about the remove and add of Worst TextView animation? Check it out below.

Smooth… Check out the Good is now GOOD :).

The Space boundary is animated, causing the text movement much smoother.



I hope you appreciate this post and it’s helpful for you. Do share with others.

You could check out my other interesting topics here.

Follow me on medium, Twitter or Facebook for little tips and learning on Android, Kotlin etc related topics. ~Elye~