La scheda non ha la larghezza massima sul dispositivo Tablet [Uso di android.support.design.widget.TabLayout]


203

Ho schede di configurazione come AGGIORNAMENTO 29/05/2015 questo post. Le schede occupano la larghezza massima sul mio Nexus 4 mobile, ma sul tablet Nexus 7 al centro e non coprono la larghezza dello schermo intero.

Schermata del Nexus 7 Schermata del Nexus 7 Nexus 4 Nexus 4


stavo lottando con lo stesso identico problema per 6 ore, ma non mi rendevo conto che aveva problemi con le schede solo ... pensa a StackOverflow ci dovrebbero essere funzionalità per votare una domanda 10 volte ...
Shirish Herwade

prova ad aggiungere altri tag alle domande ... (quindi sarà più utile per le persone come me), perché questa domanda che ho trovato sulla terza pagina del mio elenco di ricerca di Google
Shirish Herwade,

Risposte:


596

Una risposta "più semplice" presa in prestito da Kaizie sarebbe semplicemente aggiungere app:tabMaxWidth="0dp"nel tuo 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
E se ne avessi bisogno per essere scorrevole? La modifica di tabMode per supportare scroll interrompe questa soluzione.
Tiago

3
Qualche soluzione per scorrere?
sunlover3

5
Ciao .. Ho provato ad aggiungere questo. ma la scheda singola non occupa l'intera larghezza del layout della scheda.
Surinder,

3
Questa soluzione funziona anche se tabMode non è impostato. La modalità tap scorrevole non sembra supportare le funzioni di gravità piena e larghezza massima 0dp.
Julio Mendoza,

3
Perché succede però? È il comportamento predefinito? O qualcosa che non ho usato bene? Fa parte delle linee guida per impostare le schede nel mezzo? Questo non succede per me quando uso 3+ schede. Solo per 2 schede.
sviluppatore Android il

92

Ho avuto lo stesso problema e ho controllato lo stile TabLayout e ho scoperto che il suo stile predefinito è Widget.Design.TabLayoutche ha implementazioni diverse (normale, orizzontale e sw600dp).

Quello di cui abbiamo bisogno è quello per tablet (sw600dp) che ha la seguente implementazione:

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

Da questo stile useremo " tabGravity " (i cui valori possibili sono "center" o "fill") usando il valore "fill".

Ma dobbiamo andare più in profondità, e quindi vediamo che questo si estende da Base.Widget.Design.TabLayout, quale implementazione è:

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

Quindi, da questo stile dovremo sostituire " tabMaxWidth ". Nel mio caso l'ho impostato su 0dp, quindi non ha limiti.

E il mio stile sembrava così:

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

E quindi la barra delle schede riempirà l'intero schermo da un lato all'altro.


1
bella scoperta .. andare alla radice. Ma per favore evidenzia la risposta esatta in alto, sarà più facile trovare qualcuno che non vuole leggere tutta la risposta
Shirish Herwade,

ottima soluzione, strano l'aspetto dell'API che puoi controllare senza cambiare lo stile sottostante. Sembra che TabMaxWidth sia il vero colpevole
kandroidj il

3
Questo è come un episodio di Sherlock. Grazie!!
Lisa Wray,

29

Soluzione per lo scorrimento: (TabLayout.MODE_SCROLLABLE), ovvero quando hai bisogno di più di 2 schede (Schede dinamiche)

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

Passaggio 2: il layout 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" />

Passaggio 3: Nella tua attività / frammento, dove hai sempre schede.

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

    }

Funzionava solo con più di una scheda, se abbiamo una sola scheda la scheda non riempie il layout della scheda. Per risolvere il problema, ho aggiunto l'app: tabMaxWidth = "1000dp" e ha funzionato.
jzeferino,

Questo ha funzionato meglio per me. Nella mia classe di layout di scheda personalizzata, ho scavalcato addTabe impostato il peso per ogni scheda man mano che veniva aggiunta. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Justin Lee,

15

Per forzare le schede a occupare l'intera larghezza (divisa in dimensioni uguali), applicare quanto segue alla TabLayoutvista:

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

2
Solo per far sapere alla gente, questo non funziona se TabLayoutimpostato su app:tabMode=“scrollable”, farà sì che le schede diventino a lunghezza fissa (le parole lunghe verranno spostate) e le schede non scorreranno più, essenzialmente rendendo le schede "riparate" di nuovo.
Sakiboy,

5

Questo è utile che devi provare

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

lavora per me. Anche questoxmlns:app="http://schemas.android.com/apk/res-auto"


3

Per me il seguente codice ha funzionato ed è stato sufficiente.

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

2

Controlla sotto il codice per le soluzioni.

Di seguito è riportato il codice layout:

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

Nota, per il conteggio dinamico delle schede, non dimenticare di chiamare 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;
    }
}

Riferimento tratto da https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatical-8146d6101efe


2

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

A Kotlin:

Nel mio caso, se meno di 3 schede assegnerò lo stesso spazio.

Nota: se la condizione è secondo il vostro requisito

        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

Perché tutto quel lavoro frenetico? Basta mettere app:tabMode="scrollable"nel vostro TabLayout in XML. Questo è tutto.

inserisci qui la descrizione dell'immagine


1
Cosa succede se è presente una scheda 3? che non si adatta allo schermo (le schede sono dinamiche che provengono dall'API del server) contano le schede conosciute in fase di esecuzione ..
Ram Prakash Bhat,

Quindi puoi anche impostare in modo programmatico come questo tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);Anche questa è solo una proprietà da impostare per tabLayout questo non importa quante schede stai aggiungendo statiche o dinamiche.
Ali Akram,

Farà la larghezza della scheda in base alle dimensioni del testo. Controlla la mia risposta modificata con l'immagine.
Ali Akram,

Ya in quel caso la modalità tab è SCROLLABLE, quindi alla fine vedrai uno spazio vuoto che sembra strano
Ram Prakash Bhat,

1

Nella mia variante di questo problema, avevo 3 schede di dimensioni moderate che non occupavano tutta la larghezza sui tablet. Non avevo bisogno che le schede fossero scorrevoli sui tablet, poiché i tablet sono abbastanza grandi da visualizzare le schede tutte insieme senza alcuno scorrimento. Ma avevo bisogno che le schede fossero scorrevoli sui telefoni, poiché i telefoni sono troppo piccoli per visualizzare tutte le schede insieme.

La migliore soluzione nel mio caso era quella di aggiungere un res/layout-sw600dp/main_activity.xmlfile, dove il relativo TabLayout poteva avere app:tabGravity="fill"e app:tabMode="fixed". Ma nel mio normale res/layout/main_activity.xml, ho lasciato fuori app:tabGravity="fill"e app:tabMode="fixed", e app:tabMode="scrollable"invece ho avuto .


-1

Si noti che è necessario impostare anche

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

per riempire tutto lo spazio


Benvenuto in Stack Overflow. Per favore, fai il tour . Questo è un sito di domande e risposte, non un forum di discussione. Questa sezione è solo per risposte complete. Dopo aver guadagnato 50 punti reputazione chiedendo e rispondendo, sarai in grado di commentare le domande e le risposte degli altri utenti .
Chris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.