Registerkarte nimmt auf Tablet-Gerät nicht die volle Breite ein [Verwenden von android.support.design.widget.TabLayout]

202

Ich habe Setup-Registerkarten als UPDATE 29/05/2015 diesen Beitrag. Tabs nehmen auf meinem Nexus 4-Handy die volle Breite ein, auf dem Nexus 7-Tablet jedoch in der Mitte und decken nicht die volle Bildschirmbreite ab.

Nexus 7 Screenshot Nexus 7 Nexus 4 Screenshot Nexus 4

Max
quelle
Ich hatte 6 Stunden lang mit genau demselben Problem zu kämpfen, aber ich wusste nicht, dass es nur Probleme mit Tabs gibt ... denke, beim Stackoverflow sollte es Funktionen geben, um eine Frage 10 Mal zu bewerten ...
Shirish Herwade
Bitte versuchen Sie, mehr Tags zu Fragen hinzuzufügen ... (wird also für Leute wie mich hilfreicher sein), da diese Frage ich auf der dritten Seite meiner Google-Suchliste gefunden habe
Shirish Herwade

Antworten:

594

Eine "einfachere" Antwort, die von Kaizie ausgeliehen wurde, würde nur app:tabMaxWidth="0dp"in Ihrer TabLayoutXML- Datei hinzugefügt werden :

<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
quelle
19
Was ist, wenn es scrollbar sein muss? Durch Ändern des tabMode zur Unterstützung des Bildlaufs wird diese Lösung unterbrochen.
Tiago
3
Irgendeine Lösung für scrollbar?
Sunlover3
5
Hallo .. Ich habe versucht, dies hinzuzufügen. Die einzelne Registerkarte nimmt jedoch nicht die gesamte Breite des Registerkartenlayouts ein.
Rahul
3
Diese Lösung funktioniert auch, wenn der tabMode nicht festgelegt ist. Der scrollbare tapMode scheint die Funktionen der gefüllten Schwerkraft und der maximalen Breite von 0 dp nicht zu unterstützen.
Julio Mendoza
3
Warum kommt es aber vor? Ist es das Standardverhalten? Oder etwas, das ich nicht gut benutzt habe? Ist es Teil der Richtlinien, die Registerkarten in der Mitte festzulegen? Dies tritt bei mir bei Verwendung von 3+ Registerkarten nicht auf. Nur für 2 Registerkarten.
Android-Entwickler
91

Ich hatte das gleiche Problem und überprüfte den TabLayout-Stil. Dabei stellte ich fest, dass der Standardstil Widget.Design.TabLayoutunterschiedliche Implementierungen aufweist (normal, Querformat und sw600dp).

Das, was wir brauchen, ist das für Tablets (sw600dp), das die folgende Implementierung hat:

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

In diesem Stil verwenden wir " tabGravity " (mögliche Werte sind "center" oder "fill") unter Verwendung des Werts "fill".

Aber wir müssen tiefer gehen, und dann sehen wir, dass sich diese von Base.Widget.Design.TabLayoutder Implementierung erstreckt:

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

Von diesem Stil aus müssen wir also " tabMaxWidth " überschreiben . In meinem Fall habe ich es 0dpso eingestellt , dass es keine Begrenzung gibt.

Und mein Stil sah so aus:

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

Und dann füllt die Registerkartenleiste den gesamten Bildschirm von einer Seite zur anderen.

Kaizie
quelle
1
schöne Entdeckung .. zur Wurzel gehen. Aber bitte markieren Sie die genaue Antwort oben, es wird einfacher sein, jemanden zu finden, der nicht alle Antworten lesen möchte
Shirish Herwade
Tolle Lösung, komisch, wie die API aussieht. Sie können sie steuern, ohne den zugrunde liegenden Stil zu ändern. Sieht aus wie tabMaxWidth ist der wahre Schuldige
kandroidj
3
Dies ist wie eine Episode von Sherlock. Danke dir!!
Lisa Wray
29

Lösung für scrollbar: (TabLayout.MODE_SCROLLABLE), dh wann immer Sie mehr als 2 Registerkarten benötigen (dynamische Registerkarten)

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

Schritt 2: Ihr XML-Layout

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

Schritt 3: In Ihrer Aktivität / Fragment, wo immer Sie Registerkarten haben.

/**
     * 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
quelle
Dies funktionierte nur mit mehr als einer Registerkarte. Wenn wir nur eine Registerkarte haben, füllt die Registerkarte das Registerkartenlayout nicht aus. Um dieses Problem zu lösen, habe ich die App hinzugefügt: tabMaxWidth = "1000dp" und es hat funktioniert.
Jzeferino
Das hat bei mir am besten funktioniert. In meiner benutzerdefinierten Registerkartenlayoutklasse habe ich addTabdie Gewichtung für jede Registerkarte beim Hinzufügen überschrieben und festgelegt. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Justin Lee
15

Wenden Sie Folgendes auf die TabLayoutAnsicht an, um zu erzwingen, dass Registerkarten die volle Breite einnehmen (in gleiche Größen aufgeteilt) :

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
Jon Cairns
quelle
2
Wenn Sie nur die Leute wissen lassen, funktioniert dies nicht, wenn Sie auf TabLayouteingestellt sind. Dies führt dazu app:tabMode=“scrollable”, dass die Registerkarten eine feste Länge haben (lange Wörter werden umbrochen) und die Registerkarten nicht mehr verschoben werden, wodurch die Registerkarten im Wesentlichen wieder „fest“ werden.
Sakiboy
5

Dies ist hilfreich, die Sie versuchen müssen

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

arbeite für mich. Dies haben auchxmlns:app="http://schemas.android.com/apk/res-auto"

Cam Hùng Huỳnh
quelle
3

Für mich hat der folgende Code funktioniert und war genug.

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

Überprüfen Sie den folgenden Code auf Lösungen.

Unten ist der Layoutcode:

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

Beachten Sie, dass Sie für die dynamische Anzahl der Registerkarten nicht vergessen haben, setTabNumbers (tabcount) aufzurufen.

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

Referenz von https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatisch-8146d6101efe

Kuldeep Sakhiya
quelle
2

Lösung für 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" />

In Kotlin:

In meinem Fall, wenn weniger als 3 Registerkarten vorhanden sind, reserviere ich den gleichen Speicherplatz.

Hinweis: Wenn die Bedingung Ihren Anforderungen entspricht

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

Warum all diese hektische Arbeit? Legen Sie einfach app:tabMode="scrollable"in Ihrem TabLayout in XML. Das ist es.

Geben Sie hier die Bildbeschreibung ein

Ali Akram
quelle
1
Was ist, wenn es 3 Registerkarten gibt? Das passt nicht zum Bildschirm (Registerkarten sind dynamisch und stammen von der Server-API). Die Anzahl der Registerkarten ist zur Laufzeit bekannt.
Ram Prakash Bhat
Dann können Sie sogar programmgesteuert wie tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);folgt festlegen. Dies ist auch nur eine Eigenschaft, die für tabLayout festgelegt werden muss, unabhängig davon, wie viele Registerkarten Sie entweder statisch oder dynamisch hinzufügen.
Ali Akram
Die Breite der Registerkarten richtet sich nach der Textgröße. Überprüfen Sie meine bearbeitete Antwort mit dem Bild.
Ali Akram
Ya in diesem Fall Tab-Modus ist SCROLLABLE, dann am Ende sehen Sie leeren Raum, der seltsam aussieht
Ram Prakash Bhat
1

In meiner Variante dieses Problems hatte ich 3 Tabs mittlerer Größe, die auf Tablets nicht die volle Breite einnahmen. Ich brauchte nicht, dass die Registerkarten auf Tablets scrollbar sind, da Tablets groß genug sind, um die Registerkarten ohne Scrollen zusammen anzuzeigen. Die Registerkarten mussten jedoch auf Telefonen gescrollt werden können, da die Telefone zu klein sind, um alle Registerkarten zusammen anzuzeigen.

Die beste Lösung in meinem Fall war eine hinzuzufügen res/layout-sw600dp/main_activity.xmlDatei, in denen die einschlägigen TabLayout haben könnten app:tabGravity="fill"und app:tabMode="fixed". Aber in meinem regelmäßigen res/layout/main_activity.xml, verließ ich aus app:tabGravity="fill"und app:tabMode="fixed"und hatte app:tabMode="scrollable"statt.

CKP78
quelle
0

Bitte beachten Sie, dass Sie auch einstellen müssen

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

den ganzen Raum füllen

Andrew Barabash
quelle
Willkommen bei Stack Overflow. Bitte nehmen Sie an der Tour teil . Dies ist eine Frage- und Antwortseite, kein Diskussionsforum. Dieser Abschnitt enthält nur vollständige Antworten. Sobald Sie durch Fragen und Antworten 50 Reputationspunkte verdient haben, können Sie die Fragen und Antworten anderer Benutzer kommentieren .
Chris