Android TabLayout and TabItem

Android TabLayout and TabItemMyrick ChowBlockedUnblockFollowFollowingMay 31TabLayout is a common widget working with ViewPager and ViewPager2.

User can tap on each tap to go to a specific page in ViewPager directly.

The most common example is the Google Play Store app.

Screenshot of Google Play Store appIn this article, I would share my experience on styling each TabItem.

I found that the Google documentation does not synchronise with its opened source code.

Reading the corresponding source code is the best way to understand the details of each attribute.

If you are interested in the implementation and tricks of ViewPager2, you could read more in my another article.

Android ViewPager2 & TabLayoutViewPager2 is introduced in this year 2019 Google I/O and is a replacement of the old ViewPager, which was created in…medium.

comTabItemTabItem is a View which contains an icon and a text.

It has two states — selected and unselected.

It must be “attached” to a TabLayout .

However, according to the Google official documentation (see below quote) , it is a dummy View which is not actually “added” to a TabLayout.

As a result, findViewById() will always return null and developer cannot customise each tab by referring to it directly.

TabItem is a special ‘view’ which allows you to declare tab items for a TabLayout within a layout.

This view is not actually added to TabLayout, it is just a dummy which allows setting of a tab items's text, icon and custom layout.

See TabLayout for more information on how to use it.

Reference: Google documentation about TabItemIf TabLayout is linked with a ViewPager2, we can manually use the callback TabLayoutMediator.

OnConfigureTabCallback in class TabLayoutMediator to style each inflated TabItem.

To know more about the implementation and explanation, please refer to my another article:Android ViewPager2 & TabLayoutViewPager2 is introduced in this year 2019 Google I/O and is a replacement of the old ViewPager, which was created in…medium.

comTabLayoutScreenshot at the Google documentationTabLayout is aHorizontalScrollView which contains a list of TabItem.

It layouts each TabItem just like a horizontal LinearLayout.

However, it is restricted to only have TabItem as its children.

Runtime error will occur if it is not followed, see below error message:java.


RuntimeException: Unable to start activity ComponentInfo{…}: android.


InflateException: Binary XML file line #35: Only TabItem instances can be added to TabLayoutFirst of all, let’s have a look at the brief summary of attributes available for TabLayout.

According to Material Design opened source code, tabIndicatorHeight and tabSelectedTextColor are both currently depreciated but Google official documentation has not yet updated.

tabIndicatorHeight attribute at Material Component source codetabSelectedTextColor attribute at Material Component source codeHere is a list of attributes that you can jump to directly:Tab indicator attributesapp:tabIndicator — Replacement of app:tabIndicatorHeightapp:tabIndicatorColorapp:tabIndicatorGravityapp:tabIndicatorFullWidthapp:tabIndicatorAnimationDuration — Newly added by not shown at Google official documentationBackground attributesapp:tabBackgroundapp:tabRippleColorapp:tabUnboundedRippleIcon attributesapp:tabIconTintapp:tabIconTintModeText attributesapp:tabInlineLabelapp:tabTextColor — Replacement of app:tabSelectedTextColorapp:tabTextAppearancePosition attributesapp:tabContentStartapp:tabPadding, app:tabPaddingStart | Top | End | BottomSize attributesapp:tabMinWidth & app: tabMaxWidthPosition attributesapp:tabGravityMode attributesapp:tabModeTab indicator attributes1.

app:tabIndicatorFor configuring the height of tab indicator.

The default height is 2dp.

Do not use app:tabIndicatorHeight to change the height of indicator since it is now depreciated.

app:tabIndicatorHeight is now deprecated.

Instead, set the intrinsic size of the custom drawable provided to the tabIndicator attribute in order to change the indicator height.

For example, this can be done by setting the <size> property in a <shape> resource.

Reference: Line 26–28 of Material Component source codeCode for setting tab indicator dimensionDrawable resource code for declaring height2.

app:tabIndicatorColor (Self-explanatory)3.

app:tabIndicatorGravityTo define the position of tab indicator.


app:tabIndicatorFullWidthOption 1 — true (Default) : Width of indicator equals the width of TabItemOption 2 — false: Width of indicator is determined by the width of text inside TabItem.

Minimum with of indicator is set to be 24dp.

Default minimum width of indicator; Line 188–189 of Material Component source code5.

app:tabIndicatorAnimationDurationTo define the time used for the tab indicator to go from current TabItem to the selected TabItem.

By default it is 300ms declared in Material Component source code.

Line 196 of Material Component source codeBackground attributes1.

app:tabBackgroundThere are two states for TabItem — Selected & default.

Background can be a drawable state list.


app:tabRippleColor (Self-explanatory)3.

app:tabUnboundedRippleOption 1 — false (default): Ripple is bounded by the boundary of its TabItemOption 2 — true: Ripple grows beyond regardless the boundary of its TabItemIcon attributes1.

app:tabIconTintIcon tint is a layer of color which is painted on the non-transparent part of icon image.


app:tabIconTintModeThere are 6 tint modes and each one manipulates the transparency and color by different equations.

It is not recommended to use this attribute unless you clearly understand what the calculation is.

Reference: PorterDuff mode — GoogleText attributes1.

app:tabInlineLabelOption 1 — false (default): Icon is placed above the text of TabItemOption 2 — true: Icon is placed at the start of text of TabItem2.

app:tabTextColorText color can be set for both the selected and default state by color state list.

app:tabSelectedTextColor is now deprecated Instead, provide a ColorStateList to the app: tabTextColor attribute with a selected color set.

Reference: Line 76–77 of Material Component source code3.

app:tabTextAppearanceStyling text in each TabItem cannot be done directly by something like android:textSize or android:textStyle.

TextAppearance is the only available way to style it.

For more information about general TextAppearance, you could refer to the following article written by Nick Butcher@Google:What’s your text’s appearance?Understanding how to declaratively style text on Android.


comPosition attributes1.

app:tabContentStartThis attribute offset the start position of TabLayout.

However, it is tricky since there is no explanation in Google official document and setting this attribute solely does not seem to have any effect.

The only solution I can think of is reading the source code directly and see the implementation.

Below are the screenshot from source code:Default value of app:tabContentStart and app:tabModeImplementation of app:tabContentStart depends on the app:tabModeAs you can see, tabContentStart attribute is only applicable when app:tabMode="scrollable | auto" but tabMode is set to fixed by default.

This is the reason why most developers are frustrated about using this attribute.


app:tabPadding, app:tabPaddingStart | Top | End | Bottom (Self-explanatory)Size attributes1.

app:tabMinWidth & app: tabMaxWidthThe minimum and maximum width applied to each tab.

These attributes will override the tabGravity fill into center if the total width of all TabItem is smaller than the width of TabLayout.

Position attributes1.

app:tabGravityOption 1 — fill (default): Occupy the whole width of TabLayout and each tab has equal width.

Option 2 — center: All tabs are centered within TabLayout and each tab has the same width as that of the widest tab.

Mode attributes1.

app:tabModeOption 1 — fixed: Display all tab at the same time and each tab has equal width which is based on the widest tab label.

Option 2 — scrollable: A horizontally scrollable TabLayout and each tab has its own width calculated by the dimension of its text and icon.

Option 3 — auto: either scrollable or fixed with center-gravityThere are two cases:Case 1: When TabLayout is able to fit all TabItems within its bound, TabLayout is the same as:Case 2: When TabLayout is NOT able to fit all TabItems within its bound, TabLayout is under MODE_SCROLLABLE.

ConclusionTabLayout and TabItem are important UI for enhancing UX of a ViewPager.

However, the styling of TabItem is a little bit difficult due to the lack of clear explanation and description at Google official documentation.

TabItem is a dummy View which is not added to TabLayout and thus developer cannot reference it by using findViewById().

TabLayout is a HorizontalScrollView and layouts its child horizontally by default.

app:tabIndicatorHeight is depreciated and replaced by app:tabIndicator.

app:tabSelectedTextColor is depreciated and replaced by app:tabTextColor with ColorStateList.

app:tabIndicatorAnimationDuration is newly added but there are no official documentation about this in Google.

Further readings:Google official documentation — TabLayoutMaterial Design — TabLayoutGitHubMaterial Components Android TabLayout source codeGitHub Material Components Android TabLayout stylesGitHub Material Components Android TabLayout attributesPlease leave a comment if you have any.

Thank you for reading.


. More details

Leave a Reply