Playing with the new support TabLayout

  1 mins read

Today I had to implement the new TabLayout from the support library and this is my Tips&Tricks to implement the tabs in a painless way.

The default tab indicator is so thin and can’t be appreciated it if the background is similar to the indicator. The first thing to change is the tab indicator height by modifying the xml where the TabLayout is declared:

<android.support.design.widget.TabLayout app:tabIndicatorHeight="4dp"

The difference between the 1dp and 4dp is notorious:
72dptab_1dpindicator72dptabs

The height of the tabs is fixed to 48dp. The material guidelines uses 48dp when you have text only but if you want an icon the height is 72dp (Tab guidelines). So to solve it I subclassed the TabLayout and overrided onMeasure in this way:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    super.setMeasuredDimension(widthMeasureSpec,
        MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY));
}

With this code, you can set it the height at whatever value you want.

48dp tabs:
48dptabs

72dp tabs:
72dptabs

We have custom tab views and a ViewPager, so I can't use the method tabLayout.setupWithViewPager(); because I need to specify a custom view for each tab, so I created a custom layout and I use the method addTab in this way:

tabLayout.addTab(tabLayout.newTab().
          setCustomView(tab).
          setContentDescription(homeTab.getTitleId()).
          setIcon(homeTab.getIconId()).
          setText(homeTab.getTitleId()));

And later to set the movement between pager and TabLayout do this:

tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

To distribute the Tabs to all the of the width of your screen you need to set MATCH_PARENT on the TabLayout xml component and in the code set the tab gravity to GRAVITY_FILL:

tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

The last trick: If you use a tab gravity "GRAVITY_FILL" and you see a stripped text maybe is because the TabLayout is applying some insets when creating the tabs, you can fill all the available horizontal space by setting this in the TabLayout:

<android.support.design.widget.TabLayout
app:tabPaddingStart="-1dp"
app:tabPaddingEnd="-1dp"

Normal tabs:
72dptabs_nopadding

With negative horizontal padding:
72dptabs_negativepadding

Written by:

Christian Panadero Martinez

  • Anuj Mody

    how to change the tab indicator position programatically??

    • You can change the tab with viewPager.setCurrentItem(X);
      Altought the TabLayout is a HorizontalScrollView so you can use tabLayout.setScrollPosition (for dirty hacks?) 🙂

  • kavya shivaram

    How can I change the modes to make sure GRAVITY_FILL is always used? I cannot use GRAVITY_FILL with scrollable tabs. So if I am using MODE_SCROLLABLE and I load the app to a tablet, the tabs are left aligned. And If I change it to MODE_FIXED, then my text in the tabs is getting cut.

  • hsuan

    how can i set the width of tabIndicator?I hope it don’t fill the tab.

    • In short, I think you can’t do that, because the TabLayout is distributing the width evenly between all the childs, so as we can see the text “tabX” is too short to fill the width of the TabView and that’s because you’re seeing that effect. The only way to change this I think is to change the GRAVITY_FILL for GRAVITY_CENTER.

    • 王化伟

      did you do that,can you share your method ,thanks~

  • erum hannan

    i have used this code but failed to swipe and its not showing my data in viewpager fragments while when i use design tablayout instead of custom one it works fine ? pls reply me

  • erum hannan

    here is my code i m using http://pastie.org/10349229#266 pls see renderProfileData method @panavtec:disqus

    • Don’t use setupViewPager method of tablayout instead use the 2 methods that Iḿ telling you in my article:

      tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
      viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

  • Daniel Nugent

    You actually can use a custom view for each tab with a ViewPager, take a look at the Custom View section here: https://guides.codepath.com/android/google-play-style-tabs-using-tablayout

  • Puneet Akhouri

    Nice post, do you have any idea how to fix the width of each tab irrespective of the screen size. As per my design requirements, I need each tab to be of a certain width.

  • Hi, panavtec, nice post. I have a question here: Is there any method to put the indicator on the top of tablayout if I put the tablayout at the bottom of my activiy??? thanks

  • Nice post, thanks! I was trying to space the tabs equally across the width of the screen when the device is horizontal. I figured it was something simple, I just couldn’t find a good example.

  • Sage Pawan

    tabPaddingStart and tabPaddingEnd when set to -1dp is working just fine. But tabPaddingTop and tabPaddingBottom when set to -1dp wont remove the tabLayout padding. I have already set Tab gravity to fill.

  • Navid Sadiq

    I’ve tried this with com.android.support:support-v4:23.2.0 but the setOnTabSelectedListener is not working can you advise what I’m missing here. Thanks a lot

    CustomFragmentPagerAdapter adapter = new CustomFragmentPagerAdapter (getSupportFragmentManager());

    adapter.addFragment(new FirstFragment(), “One”);
    adapter.addFragment(new SecondFragment(), “Two”);
    viewPager.setAdapter(adapter);

    tabLayout.setupWithViewPager(viewPager);
    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

    tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
    super.onTabSelected(tab);

    showToast(“onTabSelected: ” + tab.getPosition());
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    super.onTabUnselected(tab);

    showToast(“onTabUnselected: ” + tab.getPosition());
    }
    });

  • gamma

    Hi, can we set the tab paddings programmatically? If so, can you provide the steps for it..Thanks..:)

  • Kaustubh Bhagwat

    How to reduce the width of tab indicator ??