TabLayout is an implementation of the Material Design tabs specification which can be found in the Android Design Support Library. It provides a horizontal layout in order to display tabs. By using it, we can easily implement tab navigation in our app to swipe between fragments.

As in our previous article, we will not show a step by step guide on how to setup a TabLayout from scratch, but rather, show some interesting points when dealing with TabLayout component. While writing this post and making a demo app we figured out it was getting lengthy, so we decided to split it up in two parts. The first one will show some common and useful features such as how to programmatically change tab icon position, tab style and tab indicator color and height. Also we will see how to handle orientation change to hold all these changes after a screen rotate. The second part is a little more tricky. It will show how to add and remove tabs dynamically and also how to handle orientation change in order to keep all current tabs (including those ones user might have added dynamically) and to skip those tabs user has deleted after you rotate your device.

This is a short video on how demo app looks like:

So, let’s see what we have for today.

Icon position

No icon

When adding a tab to the PagerAdapter, we can set a title to each tab which will be visible to the user. This title is returned by the adapter’s getPageTitle method.

We can also set/change a tab name later by calling TabLayout.Tab.setText method:

Icon only

If you want to show only an icon, you just need to set it for each tab by calling TabLayou.Tab.setIcon method:

If, for some reason a tab already contains a caption, we should also call:

As we can see, set only a caption or only an icon for a tab are pretty straightforward. But we can also show a caption and an icon together and positioning the icon the way we want: icon on the left side, icon on the right side, icon on top and icon on the bottom.

Icon and text

But when it comes to show an icon plus a caption together, things are a little more tricky. If you just add an icon as we did above and do not set an empty string to the text, depends on the “Design Support Library” version you are using, icon will be positioned in different places by default. For example, on version 23.0.1, the default behavior is to have icons on the left side of the caption. On version 23.1.0 and 25.1.0, icons are placed on the top of the text. I do not know how it behaves when using other versions, so you really need to test it and see whether the “default” icon position works for you. If so, great; otherwise, you need to provide a custom XML layout file by positioning the icon the position you want. See next section how to work with custom layouts.

Working with custom layout

When working with custom layout we need to add some code in order to make things work as we expect. First we need to inflate it, set the icon and text we want and then call TabLayout::setCustomView() to set it to the TabLayout.

This will make our tab to show the custom layout we set, but when we select a tab, we will notice the icon and text color for the selected tab will not be changed (as it would normally do when using standard layout).

Change icon and text tab color when using custom layout

So, in order for the icon and text color for a tab change based on whether it is selected or not, we need to change it manually by either providing two versions of each icon (and use a selector to make the changes happen) or programmatically by following these steps:

Tab Mode and Gravity

It is also possible to configure how tabs will be positioned on the screen. This is useful when dealing with different screen sizes and orientation. Although we can do it in the XML, if we need change it at realtime (i.e.: using a certain mode for portrait mode and another one when device is in landscape mode), we need to do it programmatically.

Fixed Tabs

This will make tabs to fullfil screen width

Fixed Center Tabs

This makes tabs to be center aligned

Scrollable Tabs

When using MODE_SCROLLABLE, if there is no room available, tabs will be scrollable:

Note that when using scrollable tabs, gravity cannot be changed. If you need your tabs to be centered when there is room, but scrollable if there is no room, you need to use another approach. Take a look in this SO question which explains how to do it.

Selecting a tab programmatically

There might be some cases we need to select a tab programmatically. If you need to achieve it, once you know the tabindex you want to select, just add the following lines:

Could not be any simpler. You can find some examples of programmatically select tabs in the BirthdayFragment class.

Toolbar scrolling

If a tab fragment contains a list with many items, while scrolling it up, toolbar will also be collapsed. But, if after toolbar is collapsed we select another tab with no list (or a list with just a few items), toolbar will keep collapsed and we cannot make it expanded again. To fix it, we can expand AppBarLayout programmatically when selecting a tab:

Note that according to the documentation, for this to work, AppBarLayout must be a direct child of a CoordinationLayout.

Tab Indicator

By default, when you select a tab, the tab indicator will use the accent color and also will have a medium height. Modifying it is pretty simple. To change the color, once you know the color you want, just call setSelectedTabIndicatorColor:

To change tab indicator height, just call setSelectedTabIndicatorHeight informing a height in pixels:

Changing main menu items based on the selected tab

While selecting tabs, we normally show different fragments for each one. Depends on the fragment you show, you might want to display different menu items on the toolbar. In order to achieve it, we just need to add specific fragment menu items in the fragment itself, and not in the activity which holds the fragments. This might seem pretty obvious (and I know it is), but I struggled a lot trying to figure out how to do it when I first used tabs, so I decided to write it down here. Maybe it can save someone a day of work. On the demo app, check PeopleFragment and WalkFragment. They both inflate specific menus which will be appended to the MainActivity’s container menu when they become visible.

Conclusion

As you can see, working with TabLayout component provided by the Design Support Library is pretty easy. Even when we need to work with custom layout, once we get the idea we see this is not complicated at all. And the result is a beautiful app which can allow users to easily navigate through your app contents.

You can find here a demo project which contains some useful menu options that provides easy access for all topics covered on this post. We also created some helper methods in order to make things clear (and reusable). You are free to use it the way you want.

Leave a comment below if you have any question.