244

I have setup tabs as UPDATE 29/05/2015 this post. Tabs take full width on my Nexus 4 mobile but on nexus 7 tablet it in center and not cover full screen width.

Nexus 7 screenshot Nexus7 Nexus 4 screenshot Nexus 4

Community
  • 1
  • 1
Max
  • 5,733
  • 4
  • 30
  • 44
  • was struggling with exact same issue for 6 hours, but I didn't realize it has issue with tabs only... think on stackoverflow there should be functionality to upvote a question 10 times... – Shirish Herwade Apr 12 '16 at 08:51
  • please try to add more tags to questions... (so will be more helpful for people like me), because this question I found on third page of my google search list – Shirish Herwade Apr 12 '16 at 08:54

13 Answers13

676

A "simpler" answer borrowed from Kaizie would just be adding app:tabMaxWidth="0dp" in your TabLayout xml:

<android.support.design.widget.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabGravity="fill"
            app:tabMode="fixed" />
Community
  • 1
  • 1
Adam Johns
  • 35,397
  • 25
  • 123
  • 176
  • 23
    What if I need it to be scrollable? Changing tabMode to support scroll breaks this solution. – Bitcoin Cash - ADA enthusiast Mar 10 '16 at 00:43
  • 5
    Any solution for scrollable? – sunlover3 Mar 18 '16 at 15:33
  • 6
    Hi.. I have tried adding this. but the single tab is not taking entire width of the tab layout. – Surinder Mar 31 '16 at 09:31
  • 1
    app:tabMaxWidth="0dp" works for me, and that also without using app:tabMode="fixed" – Shirish Herwade Apr 12 '16 at 08:59
  • 3
    This solution also works if the tabMode is not set. The scrollable tapMode doesn't appear to support the features of filled gravity and 0dp max width. – Julio Mendoza Apr 12 '16 at 21:05
  • 1
    This worked for me! I had tabGravity=fill and tabmode=fixed and as it is mentioned in the answer, setting tabMaxWidth=0dp did the trick for me! I had to do this for nexus 9. – Mr.Noob May 06 '16 at 07:47
  • 4
    Why does it occur though? Is it the default behavior? Or something I didn't use well ? Is it a part of the guidelines to set the tabs in the middle? This doesn't occur for me when using 3+ tabs. Only for 2 tabs. – android developer Jun 22 '16 at 14:16
  • this fixed a problem for me in landscape mode (even though it was working fine in portrait) – TWL Nov 22 '16 at 02:05
  • I used `ConstraintLayout` as root. To get the full width just add *app:tabGravity="fill"*. And it's working. tabMaxWidth doesn't work for me – Hasan Abdullah Dec 04 '17 at 06:37
  • @androiddeveloper did you ever find out why this only happens with two tabs specifically? – Michael Alan Huff Apr 05 '18 at 20:27
  • 2
    is there a way to set app:tabMaxWidth programmatically? – Desolator Apr 27 '18 at 01:37
  • What does [Material Design](https://material.io/design) have to say about this `tabMaxWidth` setting? Should we really set it to `0dp`? Though, the default value of `264dp` is certainly too low for larger screens. – l33t Aug 18 '20 at 21:41
101

I had the same problem and I checked the TabLayout style, and i found that its default style is Widget.Design.TabLayout which has different implementations (normal, landscape and sw600dp).

The one we need is the one for tablets (sw600dp) which has the following implementation:

<style name="Widget.Design.TabLayout" parent="Base.Widget.Design.TabLayout">
        <item name="tabGravity">center</item>
        <item name="tabMode">fixed</item>
 </style>

From this style we will use "tabGravity" (which possible values are "center" or "fill") using the "fill" value.

But we need to go deeper, and then we see that this one extends from Base.Widget.Design.TabLayout, which implementation is:

<style name="Base.Widget.Design.TabLayout" parent="android:Widget">
    <item name="tabMaxWidth">@dimen/tab_max_width</item>
    <item name="tabIndicatorColor">?attr/colorAccent</item>
    <item name="tabIndicatorHeight">2dp</item>
    <item name="tabPaddingStart">12dp</item>
    <item name="tabPaddingEnd">12dp</item>
    <item name="tabBackground">?attr/selectableItemBackground</item>
    <item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item>
    <item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>

So, from this style we will need to override "tabMaxWidth". In my case I set it to 0dp, so it has no limit.

And my style looked like this:

<style name="MyTabLayout" parent="Widget.Design.TabLayout">
        <item name="tabGravity">fill</item>
        <item name="tabMaxWidth">0dp</item>
</style>

And then the tab bar will fill the whole screen from side to side.

ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
Kaizie
  • 3,748
  • 4
  • 20
  • 19
  • 1
    nice discovery.. going to the root. But please highlight the exact answer at top, it will be easier to find someone who don't want to read all the answer – Shirish Herwade Jul 07 '16 at 08:00
  • great solution, weird how the api looks like you can control it without changing the underlying style. Looks like tabMaxWidth is the true culprit – kandroidj Aug 02 '16 at 21:45
  • 5
    This is like an episode of Sherlock. Thank you!! – Lisa Wray Jan 24 '18 at 22:01
32

Solution for scrollable: (TabLayout.MODE_SCROLLABLE), that is when ever you need more than 2 tabs (Dynamic tabs)

Step 1 : style.xml

<style name="tabCustomStyle" parent="Widget.Design.TabLayout">
            <item name="tabGravity">fill</item>
            <item name="tabMaxWidth">0dp</item>
            <item name="tabIndicatorColor">#FFFEEFC4</item>
            <item name="tabIndicatorHeight">2dp</item>
            <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
            <item name="tabSelectedTextColor">#FFFEEFC4</item>
        </style>

        <style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
            <item name="android:textSize">@dimen/tab_text_size</item>
            <item name="android:textAppearance">@style/TextAppearance.roboto_medium</item>
            <item name="textAllCaps">true</item>
        </style>
        <style name="TextAppearance.roboto_medium" parent="android:TextAppearance">
            <item name="android:fontFamily">sans-serif-medium</item>
        </style>

Step 2 : Your xml layout

<android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            style="@style/tabCustomStyle"
            android:layout_width="match_parent"
            android:layout_height="@dimen/tab_strip_height"
            android:background="@color/your_color"
            app:tabMode="scrollable"
            app:tabTextColor="@color/your_color" />

Step 3: In your Activity/Fragment where ever you have tabs.

/**
     * To allow equal width for each tab, while (TabLayout.MODE_SCROLLABLE)
     */
    private void allotEachTabWithEqualWidth() {

        ViewGroup slidingTabStrip = (ViewGroup) mTabLayout.getChildAt(0);
        for (int i = 0; i < mTabLayout.getTabCount(); i++) {
            View tab = slidingTabStrip.getChildAt(i);
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) tab.getLayoutParams();
            layoutParams.weight = 1;
            tab.setLayoutParams(layoutParams);
        }

    }
jzeferino
  • 7,700
  • 1
  • 39
  • 59
Ram Prakash Bhat
  • 1,308
  • 12
  • 21
  • This worked only with more than 1 tab, if we have only one tab the tab don't fill the tab-layout. To solve that issue i added app:tabMaxWidth="1000dp" and it worked. – jzeferino Nov 30 '16 at 21:51
  • This worked best for me. In my custom tab layout class, I overrode `addTab` and set the weight for each tab as it was added. `override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }` – Justin Lee Sep 21 '19 at 22:37
14

To force tabs to take up the full width (split into equal sizes), apply the following to the TabLayout view:

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
Jon Cairns
  • 11,783
  • 4
  • 39
  • 66
  • 6
    Just letting folks know, this does not work with if your `TabLayout` is set to `app:tabMode=“scrollable”`, it will result in the tabs becoming fixed length (long words will wrap) and the tabs will no longer slide, essentially making the tabs “fixed” again. – Sakiboy Aug 24 '17 at 20:21
7
<android.support.design.widget.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabGravity="fill"
            app:tabMode="fixed" />

work for me. This also have xmlns:app="http://schemas.android.com/apk/res-auto"

Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
6

This is helpful you must try

 <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMaxWidth="0dp"
        app:tabGravity="fill"
        app:tabMode="fixed"
        app:tabIndicatorColor="@color/white"
        app:tabSelectedTextColor="@color/white"
        app:tabTextColor="@color/orange" />
Ness Tyagi
  • 2,008
  • 24
  • 18
4

For me the following code worked and was enough.

<android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabGravity="fill"/>
Birendra Singh
  • 842
  • 11
  • 19
4

Solution for Scrollable (Kotlin)

In xml:

     <com.google.android.material.tabs.TabLayout
            android:id="@+id/home_tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabMode="scrollable"
            android:fillViewport="true"
            app:tabGravity="fill" />

In Kotlin:

In my case if less than 3 tabs I allocate equal space.

Note: If condition is as per your requirement

        if(list.size <= 3){
          allotEachTabWithEqualWidth(your_tab_layout)
        }

     fun allotEachTabWithEqualWidth(tabLayout: TabLayout) {
        tabLayout.tabMode=  TabLayout.MODE_SCROLLABLE
        val slidingTabStrip = tabLayout.getChildAt(0) as ViewGroup
        for (i in 0 until tabLayout.getTabCount()) {
            val tab = slidingTabStrip.getChildAt(i)
            val layoutParams = tab.layoutParams as LinearLayout.LayoutParams
            layoutParams.weight = 1f
            tab.layoutParams = layoutParams
        }

    }
Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
Ranjithkumar
  • 16,071
  • 12
  • 120
  • 159
4

Just did this and worked like a charm

<com.google.android.material.tabs.TabLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:tabGravity="fill"
    app:tabMaxWidth="0dp"/>
Jerin
  • 688
  • 1
  • 9
  • 21
2

Check below code for solutions.

Below is layout code:

<com.yourpackage.CustomTabLayout
    android:id="@+id/tabs"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/off_white"
    app:tabIndicatorColor="@color/primaryColor"
    app:tabIndicatorHeight="3dp"
    app:tabMode="scrollable"
    app:tabPaddingEnd="0dp"
    app:tabPaddingStart="0dp" />

Note, for dynamic tab count, don't forget to call setTabNumbers(tabcount).

import android.content.Context;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.util.
import java.lang.reflect.Field;

public class CustomTabLayout extends TabLayout
{
    private static final int WIDTH_INDEX = 0;
    private int DIVIDER_FACTOR = 3;
    private static final String SCROLLABLE_TAB_MIN_WIDTH = "mScrollableTabMinWidth";

    public CustomTabLayout(Context context) {
        super(context);
        initTabMinWidth();
    }

    public CustomTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initTabMinWidth();
    }

    public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initTabMinWidth();
    }

    public void setTabNumbers(int num)
    {
        this.DIVIDER_FACTOR = num;
        initTabMinWidth();
    }

    private void initTabMinWidth()
    {
        int[] wh = getScreenSize(getContext());
        int tabMinWidth = wh[WIDTH_INDEX] / DIVIDER_FACTOR;

        Log.v("CUSTOM TAB LAYOUT", "SCREEN WIDTH = " + wh[WIDTH_INDEX] + " && tabTotalWidth = " + (tabMinWidth*DIVIDER_FACTOR) + " && TotalTabs = " + DIVIDER_FACTOR);

        Field field;
        try {
            field = TabLayout.class.getDeclaredField(SCROLLABLE_TAB_MIN_WIDTH);
            field.setAccessible(true);
            field.set(this, tabMinWidth);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final int WIDTH_INDEX = 0;
    private static final int HEIGHT_INDEX = 1;

    public static int[] getScreenSize(Context context) {
        int[] widthHeight = new int[2];
        widthHeight[WIDTH_INDEX] = 0;
        widthHeight[HEIGHT_INDEX] = 0;

        try {
            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();

            Point size = new Point();
            display.getSize(size);
            widthHeight[WIDTH_INDEX] = size.x;
            widthHeight[HEIGHT_INDEX] = size.y;

            if (!isScreenSizeRetrieved(widthHeight))
            {
                DisplayMetrics metrics = new DisplayMetrics();
                display.getMetrics(metrics);
                widthHeight[0] = metrics.widthPixels;
                widthHeight[1] = metrics.heightPixels;
            }

            // Last defense. Use deprecated API that was introduced in lower than API 13
            if (!isScreenSizeRetrieved(widthHeight)) {
                widthHeight[0] = display.getWidth(); // deprecated
                widthHeight[1] = display.getHeight(); // deprecated
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return widthHeight;
    }

    private static boolean isScreenSizeRetrieved(int[] widthHeight) {
        return widthHeight[WIDTH_INDEX] != 0 && widthHeight[HEIGHT_INDEX] != 0;
    }
}

Reference taken from https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatically-8146d6101efe

Kuldeep Sakhiya
  • 3,172
  • 1
  • 18
  • 17
1

Why all that hectic work ? Just put app:tabMode="scrollable" in your TabLayout in XML. Thats it.

enter image description here

Ali Akram
  • 199
  • 4
  • 12
  • 1
    What if there is 3 tab? that won't fit to screen (tabs are dynamic that are coming from server API) tabs count known at run time.. – Ram Prakash Bhat Sep 26 '16 at 06:27
  • Then you can even set programmatically like this `tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);` Also this is just a property to set for tabLayout this never matter how many tabs you are adding either static or dynamic. – Ali Akram Sep 26 '16 at 06:31
  • It will make tab width according to text size.Check my edited answer with image. – Ali Akram Sep 26 '16 at 06:35
  • Ya in that case tab mode is SCROLLABLE then at the end u will see empty space thats look odd – Ram Prakash Bhat Sep 26 '16 at 06:37
1

In my variant of this problem, I had 3 tabs of moderate size which weren't taking up full width on tablets. I didn't need the tabs to be scrollable on tablets, since tablets are big enough to display the tabs all together without any scrolling. But I did need the tabs to be scrollable on phones, since phones are too small to display all the tabs together.

The best solution in my case was to add a res/layout-sw600dp/main_activity.xml file, where the relevant TabLayout could have app:tabGravity="fill" and app:tabMode="fixed". But in my regular res/layout/main_activity.xml, I left out app:tabGravity="fill" and app:tabMode="fixed", and had app:tabMode="scrollable" instead.

CKP78
  • 630
  • 8
  • 19
-1

Please note that you also need to set

  app:tabPaddingStart="-1dp"
  app:tabPaddingEnd="-1dp"

to fill all space

  • Welcome to Stack Overflow. Please take the [tour]. This is a question and answer site, not a discussion forum. This section is only for complete answers. Once you have earned 50 reputation points by asking and answering you will be able to [comment on other users' questions and answers](https://stackoverflow.com/help/privileges/comment). – ChrisGPT was on strike May 14 '20 at 17:35