Вкладка не занимает полную ширину на планшетном устройстве [Используя android.support.design.widget.TabLayout]

У меня есть вкладки настройки как UPDATE 29/05/2015 этот пост. Вкладки занимают всю ширину на моем мобильном телефоне Nexus 4, но на планшете Nexus 7 они находятся в центре и не покрывают всю ширину экрана.

Скриншот Nexus 7 Nexus7Скриншот Nexus 4 Nexus 4


person Max    schedule 15.06.2015    source источник
comment
боролся с точно такой же проблемой в течение 6 часов, но я не осознавал, что проблема только с вкладками... думаю, что в stackoverflow должна быть функция, позволяющая голосовать за вопрос 10 раз...   -  person Shirish Herwade    schedule 12.04.2016
comment
пожалуйста, попробуйте добавить больше тегов к вопросам ... (так будет полезнее для таких людей, как я), потому что этот вопрос я нашел на третьей странице моего списка поиска Google.   -  person Shirish Herwade    schedule 12.04.2016


Ответы (12)


«Более простой» ответ, позаимствованный у Kaizie, будет просто добавлять app:tabMaxWidth="0dp" в ваш 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" />
person Adam Johns    schedule 24.07.2015
comment
Что, если мне нужно, чтобы его можно было прокручивать? Изменение tabMode для поддержки прокрутки ломает это решение. - person Bitcoin Cash - ADA enthusiast; 10.03.2016
comment
Любое решение для прокрутки? - person sunlover3; 18.03.2016
comment
Привет .. Я пытался добавить это. но одна вкладка не занимает всю ширину макета вкладки. - person Surinder; 31.03.2016
comment
app:tabMaxWidth=0dp у меня работает, и это тоже без использования app:tabMode=fixed - person Shirish Herwade; 12.04.2016
comment
Это решение также работает, если tabMode не установлен. Прокручиваемый режим tapMode, по-видимому, не поддерживает функции заполненной гравитации и максимальной ширины 0dp. - person Julio Mendoza; 13.04.2016
comment
Это сработало для меня! У меня были tabGravity=fill и tabmode=fixed, и, как упоминается в ответе, установка tabMaxWidth=0dp помогла мне! Я должен был сделать это для нексуса 9. - person Mr.Noob; 06.05.2016
comment
Почему же это происходит? Это поведение по умолчанию? Или я что-то не так использовал? Является ли частью рекомендаций установка вкладок посередине? У меня этого не происходит при использовании 3+ вкладок. Только для 2 вкладок. - person android developer; 22.06.2016
comment
это решило проблему для меня в ландшафтном режиме (хотя в портретном режиме он работал нормально) - person TWL; 22.11.2016
comment
Отличный пример. Спасибо - person Faxriddin Abdullayev; 01.10.2017
comment
Я использовал ConstraintLayout как root. Чтобы получить полную ширину, просто добавьте app:tabGravity=fill. И это работает. tabMaxWidth у меня не работает - person Hasan Abdullah; 04.12.2017
comment
@androiddeveloper вы когда-нибудь узнавали, почему это происходит только с двумя вкладками? - person Michael Alan Huff; 05.04.2018
comment
есть ли способ установить приложение: tabMaxWidth программно? - person SolidSnake; 27.04.2018
comment
Что говорит материальный дизайн об этой tabMaxWidth настройке? Должны ли мы действительно установить его на 0dp? Хотя значение по умолчанию 264dp, безусловно, слишком низкое для больших экранов. - person l33t; 19.08.2020

У меня была та же проблема, и я проверил стиль TabLayout и обнаружил, что его стиль по умолчанию — Widget.Design.TabLayout, который имеет разные реализации (обычный, альбомный и sw600dp).

Нам нужна версия для планшетов (sw600dp), которая имеет следующую реализацию:

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

В этом стиле мы будем использовать "tabGravity" (возможные значения - "center" или "fill"), используя значение "fill".

Но нам нужно пойти глубже, и тогда мы видим, что этот расширяется от Base.Widget.Design.TabLayout, реализация которого такова:

<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>

Итак, из этого стиля нам нужно переопределить "tabMaxWidth". В моем случае я установил его на 0dp, поэтому он не имеет ограничений.

И мой стиль выглядел так:

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

И тогда панель вкладок заполнит весь экран из стороны в сторону.

person Kaizie    schedule 02.07.2015
comment
приятное открытие.. идем в корень. Но, пожалуйста, выделите точный ответ вверху, будет легче найти того, кто не хочет читать весь ответ. - person Shirish Herwade; 07.07.2016
comment
отличное решение, странно, как выглядит API, которым можно управлять, не меняя базовый стиль. Похоже, tabMaxWidth — истинный виновник - person kandroidj; 03.08.2016
comment
Это как эпизод из Шерлока. Спасибо!! - person Lisa Wray; 25.01.2018

Решение для прокрутки: (TabLayout.MODE_SCROLLABLE), то есть когда вам нужно более 2 вкладок (динамические вкладки)

Шаг 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>

Шаг 2: Ваш XML-макет

<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" />

Шаг 3: В вашей деятельности/фрагменте, где у вас есть вкладки.

/**
     * 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);
        }

    }
person Ram Prakash Bhat    schedule 18.08.2016
comment
Это работало только с более чем 1 вкладкой, если у нас есть только одна вкладка, вкладка не заполняет макет вкладки. Чтобы решить эту проблему, я добавил приложение: tabMaxWidth=1000dp, и это сработало. - person jzeferino; 01.12.2016
comment
Это сработало лучше всего для меня. В моем пользовательском классе макета вкладок я переопределил addTab и установил вес для каждой вкладки по мере ее добавления. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() } - person Justin Lee; 22.09.2019

Чтобы вкладки занимали всю ширину (разделялись на равные части), примените к представлению TabLayout следующее:

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
person Jon Cairns    schedule 07.07.2015
comment
Просто сообщаю людям, что это не работает, если для вашего TabLayout установлено значение app:tabMode=“scrollable”, это приведет к тому, что вкладки станут фиксированной длины (длинные слова будут перенесены), и вкладки больше не будут скользить, по сути делая вкладки снова «фиксированными». - person Sakiboy; 24.08.2017

Это полезно, вы должны попробовать

 <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" />
person Ness Tyagi    schedule 09.09.2016

<android.support.design.widget.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabGravity="fill"
            app:tabMode="fixed" />

работай на меня. Это также имеет xmlns:app="http://schemas.android.com/apk/res-auto"

person Cam Hùng Huỳnh    schedule 22.07.2016

Для меня следующий код работал и был достаточно.

<android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabGravity="fill"/>
person Birendra Singh    schedule 04.04.2016

Решение для прокрутки (Kotlin)

В 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" />

В Котлине:

В моем случае, если меньше 3 вкладок, я выделяю равное пространство.

Примечание. Если условия соответствуют вашим требованиям

        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
        }

    }
person Ranjith Kumar    schedule 14.08.2019

Проверьте приведенный ниже код для решения.

Ниже приведен код макета:

<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" />

Обратите внимание: для динамического подсчета вкладок не забудьте вызвать 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;
    }
}

Ссылка взята с https://medium. com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablelayout-programmatically-8146d6101efe

person Kuldeep Sakhiya    schedule 29.07.2017

Зачем вся эта лихорадочная работа? Просто поместите app:tabMode="scrollable" в свой TabLayout в XML. Вот и все.

введите здесь описание изображения

person Ali Akram    schedule 26.09.2016
comment
А если 3 вкладки? которые не помещаются на экране (вкладки являются динамическими, которые поступают из серверного API), число вкладок известно во время выполнения. - person Ram Prakash Bhat; 26.09.2016
comment
Затем вы даже можете установить программно, как это tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); Также это просто свойство, которое нужно установить для tabLayout, независимо от того, сколько вкладок вы добавляете, будь то статические или динамические. - person Ali Akram; 26.09.2016
comment
Это сделает ширину вкладки в соответствии с размером текста. Проверьте мой отредактированный ответ с изображением. - person Ali Akram; 26.09.2016
comment
Да, в этом случае режим вкладок ПРОКРУТКА, тогда в конце вы увидите пустое пространство, которое выглядит странно - person Ram Prakash Bhat; 26.09.2016

В моем варианте этой проблемы у меня было 3 вкладки среднего размера, которые не занимали полную ширину на планшетах. Мне не нужно было прокручивать вкладки на планшетах, поскольку планшеты достаточно велики, чтобы отображать вкладки все вместе без какой-либо прокрутки. Но мне нужно было, чтобы вкладки можно было прокручивать на телефонах, поскольку телефоны слишком малы, чтобы отображать все вкладки вместе.

Лучшим решением в моем случае было добавить файл res/layout-sw600dp/main_activity.xml, где соответствующий TabLayout мог бы иметь app:tabGravity="fill" и app:tabMode="fixed". Но в своем обычном res/layout/main_activity.xml я пропустил app:tabGravity="fill" и app:tabMode="fixed" и вместо них поставил app:tabMode="scrollable".

person CKP78    schedule 15.02.2017

Обратите внимание, что вам также необходимо установить

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

чтобы заполнить все пространство

person Andrew Barabash    schedule 14.05.2020
comment
Добро пожаловать в Stack Overflow. Пройдите тур. Это сайт вопросов и ответов, а не дискуссионный форум. Этот раздел предназначен только для полных ответов. После того, как вы заработаете 50 очков репутации, задавая вопросы и отвечая на них, вы сможете комментировать вопросы и ответы других пользователей. - person Chris; 14.05.2020