Tab not taking full width on Tablet device [Using android.support.design.widget.TabLayout]
Asked Answered
C

13

245

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

Crescen answered 15/6, 2015 at 11:16 Comment(2)
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...Doronicum
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 listDoronicum
S
685

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" />
Sitarski answered 24/7, 2015 at 22:24 Comment(12)
What if I need it to be scrollable? Changing tabMode to support scroll breaks this solution.Pliny
Any solution for scrollable?Chitin
Hi.. I have tried adding this. but the single tab is not taking entire width of the tab layout.Strawflower
app:tabMaxWidth="0dp" works for me, and that also without using app:tabMode="fixed"Doronicum
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.Eastern
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.Deemster
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.Refection
this fixed a problem for me in landscape mode (even though it was working fine in portrait)Fourgon
I used ConstraintLayout as root. To get the full width just add app:tabGravity="fill". And it's working. tabMaxWidth doesn't work for meChemism
@androiddeveloper did you ever find out why this only happens with two tabs specifically?Stempien
is there a way to set app:tabMaxWidth programmatically?Sleepless
What does Material 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.Pickings
T
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.

Tonga answered 2/7, 2015 at 15:0 Comment(3)
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 answerDoronicum
great solution, weird how the api looks like you can control it without changing the underlying style. Looks like tabMaxWidth is the true culpritVitkun
This is like an episode of Sherlock. Thank you!!Brackish
E
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);
        }

    }
Elater answered 18/8, 2016 at 12:22 Comment(2)
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.Bihari
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() }Menard
G
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);
Godinez answered 7/7, 2015 at 9:24 Comment(1)
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.Knish
S
8
<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"

Shanaeshanahan answered 22/7, 2016 at 7:42 Comment(0)
C
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" />
Cobden answered 9/9, 2016 at 10:6 Comment(0)
D
5

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"/>
Dipnoan answered 1/10, 2021 at 10:57 Comment(0)
A
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"/>
Asparagus answered 4/4, 2016 at 14:50 Comment(0)
P
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
        }

    }
Propagandize answered 14/8, 2019 at 14:51 Comment(0)
B
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

Bistro answered 29/7, 2017 at 6:53 Comment(0)
C
1

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

enter image description here

Cardiff answered 26/9, 2016 at 6:23 Comment(4)
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..Elater
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.Cardiff
It will make tab width according to text size.Check my edited answer with image.Cardiff
Ya in that case tab mode is SCROLLABLE then at the end u will see empty space thats look oddElater
E
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.

Expansion answered 15/2, 2017 at 15:5 Comment(0)
R
-1

Please note that you also need to set

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

to fill all space

Reserved answered 14/5, 2020 at 13:47 Comment(1)
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.Firenze

© 2022 - 2024 — McMap. All rights reserved.