L'onglet ne prend pas toute la largeur sur la tablette [Utilisation d'android.support.design.widget.TabLayout]

203

J'ai des onglets de configuration comme UPDATE 29/05/2015 this post. Les onglets prennent toute leur largeur sur mon Nexus 4 mobile, mais sur la tablette Nexus 7, ils sont au centre et ne couvrent pas toute la largeur de l'écran.

Capture d'écran du Nexus 7 Capture d'écran du Nexus7 Nexus 4 Nexus 4

Max
la source
a été aux prises avec exactement le même problème pendant 6 heures, mais je ne savais pas qu'il avait un problème avec les onglets uniquement ... pensez sur stackoverflow qu'il devrait y avoir des fonctionnalités pour voter 10 fois une question ...
Shirish Herwade
veuillez essayer d'ajouter plus de balises aux questions ... (cela sera donc plus utile pour les gens comme moi), car cette question que j'ai trouvée sur la troisième page de ma liste de recherche Google
Shirish Herwade

Réponses:

596

Une réponse "plus simple" empruntée à Kaizie serait simplement d'ajouter app:tabMaxWidth="0dp"dans votre 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" />
Adam Johns
la source
19
Et si j'en ai besoin pour faire défiler? Changer tabMode pour prendre en charge le défilement rompt cette solution.
Tiago
3
Une solution pour faire défiler?
sunlover3
5
Salut .. J'ai essayé d'ajouter ceci. mais l'onglet unique ne prend pas toute la largeur de la disposition des onglets.
Surinder
3
Cette solution fonctionne également si le tabMode n'est pas défini. Le tapMode déroulant ne semble pas prendre en charge les fonctionnalités de gravité remplie et de largeur maximale de 0 dp.
Julio Mendoza
3
Pourquoi cela se produit-il cependant? Est-ce le comportement par défaut? Ou quelque chose que je n'ai pas bien utilisé? Cela fait-il partie des lignes directrices pour définir les onglets au milieu? Cela ne se produit pas pour moi lors de l'utilisation de 3+ onglets. Uniquement pour 2 onglets.
développeur Android
92

J'ai eu le même problème et j'ai vérifié le style TabLayout, et j'ai trouvé que son style par défaut est celui Widget.Design.TabLayoutqui a différentes implémentations (normal, paysage et sw600dp).

Celui dont nous avons besoin est celui pour les tablettes (sw600dp) qui a l'implémentation suivante:

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

A partir de ce style, nous utiliserons " tabGravity " (dont les valeurs possibles sont "center" ou "fill") en utilisant la valeur "fill".

Mais nous devons aller plus loin, puis nous voyons que celle-ci s'étend, à partir de Base.Widget.Design.TabLayoutlaquelle la mise en œuvre est:

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

Donc, à partir de ce style, nous devrons remplacer " tabMaxWidth ". Dans mon cas, je l'ai réglé sur 0dp, il n'a donc pas de limite.

Et mon style ressemblait à ceci:

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

Et puis la barre d'onglets remplira tout l'écran d'un côté à l'autre.

Kaizie
la source
1
belle découverte .. aller à la racine. Mais s'il vous plaît mettez en surbrillance la réponse exacte en haut, il sera plus facile de trouver quelqu'un qui ne veut pas lire toute la réponse
Shirish Herwade
excellente solution, bizarre à quoi ressemble l'api, vous pouvez le contrôler sans changer le style sous-jacent. On dirait que tabMaxWidth est le vrai coupable
kandroidj
3
C'est comme un épisode de Sherlock. Je vous remercie!!
Lisa Wray le
29

Solution pour faire défiler: (TabLayout.MODE_SCROLLABLE), c'est-à-dire quand vous avez besoin de plus de 2 onglets (onglets dynamiques)

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

Étape 2: votre mise en page 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" />

Étape 3: Dans votre activité / fragment où que vous ayez des onglets.

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

    }
Ram Prakash Bhat
la source
Cela ne fonctionnait qu'avec plus d'un onglet, si nous n'avons qu'un seul onglet, l'onglet ne remplit pas la disposition des onglets. Pour résoudre ce problème, j'ai ajouté l'application: tabMaxWidth = "1000dp" et cela a fonctionné.
jzeferino
Cela a fonctionné le mieux pour moi. Dans ma classe de présentation d'onglets personnalisée, j'ai remplacé addTabet défini le poids de chaque onglet lors de son ajout. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Justin Lee
15

Pour forcer les onglets à occuper toute la largeur (divisés en tailles égales), appliquez ce qui suit à la TabLayoutvue:

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
Jon Cairns
la source
2
Juste pour faire savoir aux gens, cela ne fonctionne pas si votre TabLayoutest défini sur app:tabMode=“scrollable”, cela entraînera la longueur fixe des onglets (les mots longs seront enroulés) et les onglets ne glisseront plus, ce qui rendra les onglets "fixes" à nouveau.
Sakiboy
5

C'est utile, vous devez essayer

 <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" />
Ness Tyagi
la source
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" />

travaille pour moi. Cela a égalementxmlns:app="http://schemas.android.com/apk/res-auto"

Cam Hùng Huỳnh
la source
3

Pour moi, le code suivant a fonctionné et était suffisant.

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

Consultez le code ci-dessous pour trouver des solutions.

Voici le code de mise en page:

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

Remarque, pour le nombre d'onglets dynamique, n'oubliez pas d'appeler 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;
    }
}

Référence tirée de https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatically-8146d6101efe

Kuldeep Sakhiya
la source
2

Solution pour Scrollable (Kotlin)

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

À Kotlin:

Dans mon cas, si moins de 3 onglets, j'alloue un espace égal.

Remarque: Si la condition est selon votre condition

        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
        }

    }
Ranjith Kumar
la source
1

Pourquoi tout ce travail mouvementé? Mettez simplement app:tabMode="scrollable"votre TabLayout en XML. C'est tout.

entrez la description de l'image ici

Ali Akram
la source
1
Et s'il y a 3 onglets? qui ne correspondent pas à l'écran (les onglets sont dynamiques qui proviennent de l'API du serveur) le nombre d'onglets est connu au moment de l'exécution.
Ram Prakash Bhat
Ensuite, vous pouvez même définir un programme comme celui-ci. tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);Il s'agit également d'une propriété à définir pour tabLayout, quel que soit le nombre d'onglets que vous ajoutez, statiques ou dynamiques.
Ali Akram
Cela fera la largeur de l'onglet en fonction de la taille du texte.Vérifiez ma réponse modifiée avec l'image.
Ali Akram
Ya dans ce cas, le mode de tabulation est DÉFILEUR, puis à la fin, vous verrez un espace vide qui semble étrange
Ram Prakash Bhat
1

Dans ma variante de ce problème, j'avais 3 onglets de taille moyenne qui ne prenaient pas toute la largeur sur les tablettes. Je n'avais pas besoin que les onglets puissent défiler sur les tablettes, car les tablettes sont assez grandes pour afficher les onglets tous ensemble sans défilement. Mais j'avais besoin que les onglets puissent défiler sur les téléphones, car les téléphones sont trop petits pour afficher tous les onglets ensemble.

La meilleure solution dans mon cas était d'ajouter un res/layout-sw600dp/main_activity.xmlfichier, où le TabLayout pertinent pourrait avoir app:tabGravity="fill"et app:tabMode="fixed". Mais dans mon habitué res/layout/main_activity.xml, j'ai laissé de côté app:tabGravity="fill"et app:tabMode="fixed", et j'ai eu à la app:tabMode="scrollable"place.

CKP78
la source
-1

Veuillez noter que vous devez également définir

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

pour remplir tout l'espace

Andrew Barabash
la source
Bienvenue dans Stack Overflow. Veuillez faire le tour . Il s'agit d'un site de questions et réponses, pas d'un forum de discussion. Cette section est uniquement pour les réponses complètes. Une fois que vous avez gagné 50 points de réputation en posant des questions et en y répondant, vous pourrez commenter les questions et réponses des autres utilisateurs .
Chris