Set Tab Minimum Width of Scrollable TabLayout Programmatically

Elsen Novraditya
4 min readMar 20, 2016

--

Search Result Screen from Coral Android App

Hello everyone! In this post, i am going to share about how to set tab’s minimum width for Scrollable TabLayout programmatically. I hope it could help all of you that has the same problem with me :D

As you can see, the picture above is an example of TabLayout in MODE_SCROLLABLE. The tab’s minimum width is set programmatically. Yeah, that is the awesome search result screen in Coral Android App (ehem :p).

There are actually only three tabs. So, why not just set the tab mode to MODE_FIXED? Well, the tab’s title is dynamic according to the search result. If i use MODE_FIXED and the title is long, it will not show the whole title. Here is the picture.

Tab’s title is cut with MODE_FIXED

So, i need to set the mode to MODE_SCROLLABLE. But, the new problem occurs. If the tab’s title is short, there will be an empty space on the right. Here is the picture.

Empty space on the right

Even if i set the tabGravity to fill and the layout_width to match_parent, it doesn’t make all the tabs fill the screen width. And if i set the tabGravity to center and the layout_width to wrap_content, it doesn’t make all the tabs centered. I have tried in support:design:23.1.1 and support:design:23.2.1 but it is still the same.

Hmmm. So, what should i do? Actually there is an attribute tabMinWidth that could be used to customise the tab’s minimum width. This attribute can only be modified in xml. We could find the right value to make the tabs fill the screen width. But, what will it look like on the other devices? There are tons of Android devices out there with different screen size. Too Bad! We cannot rely on that.

So, is it impossible? Wait! Nothing is impossible! lol. Let’s take a look at the TabLayout source code. Let’s see how the tabMinWidth attribute works. After i looked into the source code, i found these.

mRequestedTabMinWidth and mScrollableTabMinWidth fields
mRequestedTabMinWidth is assigned with the value from tabMinWidth attribute inside the constructor
mScrollableTabMinWidth is assigned with default value inside the constructor
The constructor that initialises mRequestedTabMinWidth and mScrollableTabMinWidth
The usage of mRequestedTabMinWidth and mScrollableTabMinWidth in getTabMinWidth
The usage of getTabMinWidth in creating tab view
The usage of getTabMinWidth in updating tab view

Wow, we found a new hope! \:D/ From these finding, we know that the tabMinWidth attribute is assigned to mRequestedTabMinWidth inside the constructor. This will be used in getTabMinWidth method. The getTabMinWidth method itself will be called in createTabView and updateTabViews. So, mRequestedTabMinWidth will determine the tab’s minimum width.

The logic of getTabMinWidth is if the mRequestedTabMinWidth value does not equal to INVALID_WIDTH then return mRequestedTabMinWidth value. Else, use the default value. The default value itself has a logic. If the tab mode is MODE_SCROLLABLE, return mScrollableTabMinWidth value, otherwise (MODE_FIXED) return zero. So, mScrollableTabMinWidth will determine the tab’s minimum width as well.

So, there are two ways to set the tab’s minimum width. Set the mRequestedTabMinWidth or set the mScrollableTabMinWidth. Since my TabLayout mode is in MODE_SCROLLABLE, let’s choose to set the mScrollableTabMinWidth. Ummm, but, how do we set this field? Since this field has a private final modifier. GGWP guys! Impossible!

Hey, Wait! Nothing is impossible right? ;) There is “something” called Reflection. We could use reflection to modify that private final field. So here are the steps:

  • Create a custom class that extends the TabLayout. Let’s name it CustomTabLayout.
  • Override all the constructor. Call super at the first line.
  • Create a method to modify the value of mScrollableTabMinWidth. Let’s name the method initTabMinWidth. Call this method after the super call inside the constructor.
  • Inside initTabMinWidth, find out the screen width size. This will be used to determine the new tab’s minimum width. For me, the tab’s minimum width is one third of the screen width, since the tabs are just three.
  • After we have the desired tab’s minimum width, let’s assign it to the mScrollableTabMinWidth field of the TabLayout using reflection technique. You could find the detailed code below.
  • Since we modify the mScrollableTabMinWidth, set the tabMode to scrollable. Also don’t set the tabMinWidth in xml or it will be useless.

That’s all! Let’s look whether it works or not :D

Products tab with one third of screen width
Hashtags tab with one third of screen width
Users tab with one third of screen width

Wohoooo! It works now! \:D/ All the tabs filled the screen width although the tab’s title is short. Thank you awesome people, hope it helps :)

*Coral is hiring. Let’s join our cool team!

--

--

Elsen Novraditya

Initiator, developer, and protector of Selly | Love music and sports | Everything is possible as long as you have a will to do it