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


203

У меня есть вкладки настройки, как ОБНОВЛЕНИЕ 29/05/2015 этот пост. На моем мобильном Nexus 4 вкладки занимают всю ширину, а на планшете Nexus 7 - в центре и не покрывают всю ширину экрана.

Скриншот Nexus 7 Скриншот Нексус 7 Nexus 4 Нексус 4


боролась с той же самой проблемой в течение 6 часов, но я не осознавал, что она имеет проблему только с вкладками ... думаю, в stackoverflow должна быть функциональность, чтобы поднять вопрос 10 раз ...
Шириш Хервейд

пожалуйста, попробуйте добавить больше тегов к вопросам ... (это будет более полезно для таких людей, как я), потому что этот вопрос я нашел на третьей странице моего списка поиска в Google
Shirish Herwade

Ответы:


596

«Более простой» ответ, заимствованный у Кейзи, будет просто добавить app:tabMaxWidth="0dp"в ваш TabLayoutXML:

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

19
Что если мне нужно, чтобы его можно было прокручивать? Изменение tabMode для поддержки прокрутки ломает это решение.
Тиаго

3
Любое решение для прокрутки?
sunlover3

5
Привет .. Я попытался добавить это. но одна вкладка не занимает всю ширину макета вкладки.
Суриндер

3
Это решение также работает, если tabMode не установлен. Режим прокрутки tapMode не поддерживает функции заполненной гравитации и максимальной ширины 0dp.
Хулио Мендоса

3
Почему это происходит, хотя? Это поведение по умолчанию? Или что-то, что я не использовал хорошо? Является ли частью руководящих принципов, чтобы установить вкладки в середине? Это не происходит для меня при использовании 3+ вкладок. Только для 2 вкладок.
Android-разработчик

92

У меня была та же проблема, и я проверил стиль TabLayout, и я обнаружил, что его стиль по умолчанию Widget.Design.TabLayoutимеет разные реализации (normal, landscape и 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>

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


1
хорошее открытие .. иду в корень. Но, пожалуйста, выделите точный ответ сверху, вам будет легче найти человека, который не хочет читать весь ответ
Шириш Хервейд,

отличное решение, странно, как API выглядит, как вы можете управлять им, не меняя основной стиль. Похоже, tabMaxWidth - настоящий виновник
kandroidj

3
Это похоже на эпизод с Шерлоком. Спасибо!!
Лиза Рэй

29

Решение для прокрутки: (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);
        }

    }

Это работало только с более чем одной вкладкой, если у нас есть только одна вкладка, вкладка не заполняет макет вкладки. Чтобы решить эту проблему, я добавил приложение: tabMaxWidth = "1000dp", и это сработало.
Jzeferino

Это сработало лучше для меня. В моем собственном классе макета вкладок я переопределил addTabи установил вес каждой вкладки, как она была добавлена. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Джастин Ли

15

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

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);

2
Просто сообщите людям, что это не работает, если для вас TabLayoutустановлено значение app:tabMode=“scrollable”, это приведет к тому, что вкладки станут фиксированной длины (длинные слова будут переноситься), и вкладки больше не будут скользить, по существу делая вкладки «фиксированными» снова.
Сакибой

5

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

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

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


3

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

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

2

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

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

<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-tablayout-programmatics-8146d6101efe


2

Решение для Scrollable (Котлин)

В 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) {
        mTabLayout.tabMode=  TabLayout.MODE_FIXED
        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
        }

    }

1

Почему все это беспокойная работа? Просто вставьте app:tabMode="scrollable"ваш TabLayout в XML. Это оно.

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


1
Что делать, если есть 3 вкладки? это не подходит к экрану (вкладки динамические, которые поступают из серверного API), количество вкладок известно во время выполнения ..
Рам Пракаш Бхат

Тогда вы даже можете установить программно, как это. tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);Это просто свойство для tabLayout, это не имеет значения, сколько вкладок вы добавляете, статические или динамические.
Али Акрам

Ширина вкладки будет соответствовать размеру текста. Проверьте мой отредактированный ответ с изображением.
Али Акрам

Если в этом случае режим вкладок будет прокручиваемым, то в конце вы увидите пустое пространство, которое выглядит странно
Рам Пракаш Бхат

1

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

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


-1

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

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

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


Добро пожаловать в стек переполнения. Пожалуйста, возьмите тур . Это сайт вопросов и ответов, а не дискуссионный форум. Этот раздел только для полных ответов. Как только вы наберете 50 очков репутации, задавая вопросы и отвечая на них, вы сможете комментировать вопросы и ответы других пользователей .
Крис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.