Karta nie przyjmuje pełnej szerokości na tablecie [Korzystanie z android.support.design.widget.TabLayout]


202

Mam zakładki instalacyjne jako UPDATE 29/05/2015 tego postu. Karty biorą pełną szerokość na moim telefonie Nexus 4, ale na tablecie Nexus 7 - na środku i nie pokrywają pełnej szerokości ekranu.

Zrzut ekranu Nexusa 7 Zrzut ekranu Nexus 7 Nexusa 4 Nexus 4


zmagał się z tym samym problemem przez 6 godzin, ale nie zdawałem sobie sprawy, że ma problem tylko z kartami ... pomyśl o przepełnieniu stosu powinna istnieć funkcjonalność, aby wypowiedzieć pytanie 10 razy ...
Shirish Herwade

spróbuj dodać więcej tagów do pytań ... (tak będzie bardziej pomocne dla osób takich jak ja), ponieważ to pytanie znalazłem na trzeciej stronie mojej listy wyszukiwania w Google
Shirish Herwade

Odpowiedzi:


595

„Prostsza” odpowiedź pożyczona od Kaizie wystarczy dodać app:tabMaxWidth="0dp"w plikuTabLayout 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" />

19
Co jeśli potrzebuję go do przewijania? Zmiana tabMode na obsługę przewijania psuje to rozwiązanie.
Tiago,

3
Jakieś rozwiązanie dla przewijalnego?
sunlover3

5
Cześć .. Próbowałem dodać to. ale pojedyncza karta nie zajmuje całej szerokości układu karty.
Rahul

3
To rozwiązanie działa również, jeśli tabMode nie jest ustawiony. Przewijalny tryb tapMode nie obsługuje funkcji wypełnionej grawitacji i maksymalnej szerokości 0dp.
Julio Mendoza,

3
Dlaczego tak się dzieje? Czy to jest domyślne zachowanie? A może coś, czego nie użyłem dobrze? Czy ustawianie zakładek na środku jest częścią wytycznych? Nie zdarza mi się to, gdy korzystam z kart 3+. Tylko dla 2 kart.
programista Androida

91

Miałem ten sam problem i sprawdziłem styl TabLayout i stwierdziłem, że jego domyślny styl Widget.Design.TabLayoutma różne implementacje (normal, landscape i sw600dp).

Potrzebujemy tylko tabletu (sw600dp), który ma następującą implementację:

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

Z tego stylu użyjemy „ tabGravity ” (możliwymi wartościami są „środek” lub „wypełnienie”) przy użyciu wartości „wypełnienie”.

Musimy jednak pójść głębiej, a potem widzimy, że ten rozciąga się, od Base.Widget.Design.TabLayoutktórego wdrożenia jest:

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

Dlatego z tego stylu będziemy musieli przesłonić „ tabMaxWidth ”. W moim przypadku ustawiłem to 0dp, więc nie ma limitu.

Mój styl wyglądał tak:

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

A następnie pasek kart wypełni cały ekran z boku na bok.


1
miłe odkrycie ... idę do korzenia. Ale proszę zaznaczyć dokładną odpowiedź u góry, łatwiej będzie znaleźć kogoś, kto nie chce przeczytać całej odpowiedzi
Shirish Herwade,

świetne rozwiązanie, dziwne, jak wygląda interfejs API, możesz nim sterować bez zmiany stylu. Wygląda na to, że tabMaxWidth jest prawdziwym winowajcą
kandroidj

3
To jest jak odcinek Sherlocka. Dziękuję Ci!!
Lisa Wray

29

Rozwiązanie dla przewijalnego: (TabLayout.MODE_SCROLLABLE), czyli wtedy, gdy potrzebujesz więcej niż 2 kart (Dynamiczne karty)

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

Krok 2: Twój układ 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" />

Krok 3: W swojej aktywności / fragmencie, gdziekolwiek masz zakładki.

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

    }

Działa to tylko z więcej niż 1 kartą, jeśli mamy tylko jedną kartę, karta nie wypełnia układu tabulacji. Aby rozwiązać ten problem, dodałem aplikację: tabMaxWidth = "1000dp" i działało.
jzeferino

To działało dla mnie najlepiej. W mojej niestandardowej klasie układu zakładek przesłoniłem addTabi ustawiłem wagę każdej zakładki w miarę dodawania. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Justin Lee,

15

Aby zmusić tabulatory do zajęcia pełnej szerokości (podzielenia na równe rozmiary), zastosuj do TabLayoutwidoku następujące elementy :

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

2
Po prostu informując ludzi, nie działa to, jeśli twoje TabLayoutustawienie jest ustawione app:tabMode=“scrollable”, spowoduje to, że zakładki będą miały stałą długość (długie słowa będą się owijać), a zakładki nie będą się przesuwać, co zasadniczo sprawi, że zakładki znów się „naprawią”.
Sakiboy,

5

Jest to pomocne, musisz spróbować

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

Pracuj dla mnie. To też maxmlns:app="http://schemas.android.com/apk/res-auto"


3

Dla mnie poniższy kod działał i był wystarczający.

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

2

Sprawdź poniższe kody, aby znaleźć rozwiązania.

Poniżej znajduje się kod układu:

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

Uwaga: w celu dynamicznego liczenia kart nie zapomnij wywołać 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;
    }
}

Referencje pochodzą z https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatically-8146d6101efe


2

Rozwiązanie do przewijania (Kotlin)

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

W Kotlinie:

W moim przypadku, jeśli mniej niż 3 karty, przydzielam równe miejsce.

Uwaga: Jeśli warunek jest zgodny z wymaganiami

        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

Dlaczego cała ta gorączkowa praca? Wystarczy umieścić app:tabMode="scrollable"TabLayout w XML. Otóż ​​to.

wprowadź opis zdjęcia tutaj


1
Co jeśli są 3 zakładki? które nie będą pasować do ekranu (karty są dynamiczne, które pochodzą z API serwera) liczba kart znanych w czasie wykonywania ..
Ram Prakash Bhat

Następnie możesz nawet ustawić programowo w tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);ten sposób. Jest to tylko właściwość ustawiona dla tabLayout, nie ma znaczenia, ile kart dodajesz statycznie czy dynamicznie.
Ali Akram

Zmieni szerokość tabulatora zgodnie z rozmiarem tekstu. Sprawdź moją edytowaną odpowiedź obrazem.
Ali Akram

Tak, w tym przypadku tryb tabulacji jest PRZEWIJANY, a na końcu zobaczysz puste miejsce, które wygląda dziwnie
Ram Prakash Bhat

1

W moim wariancie tego problemu miałem 3 zakładki umiarkowanego rozmiaru, które nie zajmowały pełnej szerokości na tabletach. Nie potrzebowałem przewijania kart na tabletach, ponieważ tablety są wystarczająco duże, aby wyświetlać wszystkie karty bez przewijania. Ale potrzebowałem kart do przewijania na telefonach, ponieważ telefony są zbyt małe, aby wyświetlić wszystkie karty razem.

Najlepszym rozwiązaniem w moim przypadku było dodanie res/layout-sw600dp/main_activity.xmlpliku, w którym odpowiedni TabLayout mógłby mieć app:tabGravity="fill"i app:tabMode="fixed". Ale w moich stałych res/layout/main_activity.xml, wyszedłem na zewnątrz app:tabGravity="fill"i app:tabMode="fixed", i miał app:tabMode="scrollable"zamiast.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.