A guia não ocupa largura total no dispositivo Tablet [Usando android.support.design.widget.TabLayout]

203

Tenho guias de instalação como ATUALIZAÇÃO 29/05/2015 nesta postagem. As guias têm largura total no meu celular Nexus 4, mas no tablet do nexus 7 ele fica no centro e não cobre a largura da tela inteira.

Captura de tela do Nexus7 Nexus 7 Nexus 4

Máx.
fonte
estava lutando com exatamente o mesmo problema para 6 horas, mas eu não sabia que ele tem problema apenas com abas ... pense em stackoverflow deve haver funcionalidade para upvote uma pergunta 10 vezes ...
Shirish Herwade
por favor, tente adicionar mais tags a perguntas ... (por isso vai ser mais útil para pessoas como eu), porque esta pergunta eu encontrei na terceira página da minha lista de busca Google
Shirish Herwade

Respostas:

596

Uma resposta "mais simples" emprestada do Kaizie estaria apenas adicionando app:tabMaxWidth="0dp"no seu 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
fonte
19
E se eu precisar que seja rolável? Alterar tabMode para oferecer suporte à rolagem quebra esta solução.
Tiago
3
Alguma solução para rolagem?
sunlover3
5
Oi .. Eu tentei adicionar isso. mas a guia única não ocupa toda a largura do layout da guia.
Surinder
3
Esta solução também funciona se o tabMode não estiver definido. O tapMode rolável não parece suportar os recursos de gravidade preenchida e largura máxima de 0dp.
Julio Mendoza
3
Por que isso ocorre? É o comportamento padrão? Ou algo que não usei bem? Faz parte das diretrizes definir as guias no meio? Isso não ocorre para mim ao usar 3 ou mais guias. Apenas para 2 abas.
desenvolvedor android
92

Eu tive o mesmo problema e verifiquei o estilo TabLayout, e descobri que seu estilo padrão é o de Widget.Design.TabLayoutimplementações diferentes (normal, paisagem e sw600dp).

O que precisamos é o de tablets (sw600dp), que possui a seguinte implementação:

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

Nesse estilo, usaremos " tabGravity " (cujos valores possíveis são "centro" ou "preenchimento") usando o valor "preenchimento".

Mas precisamos ir mais fundo e, em seguida, vemos que este se estende de Base.Widget.Design.TabLayoutqual implementação é:

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

Portanto, a partir deste estilo, precisaremos substituir " tabMaxWidth ". No meu caso, defino-o para 0dpque ele não tenha limites.

E meu estilo ficou assim:

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

E então a barra de guias preencherá a tela inteira de um lado para o outro.

Kaizie
fonte
1
boa descoberta .. indo para a raiz. Mas, por favor destacar a resposta exata no topo, será mais fácil encontrar alguém que não quer ler toda a resposta
Shirish Herwade
ótima solução, estranho como a API parece, você pode controlá-la sem alterar o estilo subjacente. Looks como tabMaxWidth é o verdadeiro culpado
kandroidj
3
É como um episódio de Sherlock. Obrigado!!
Lisa Wray
29

Solução para rolagem: (TabLayout.MODE_SCROLLABLE), ou seja, sempre que você precisar de mais de 2 guias (guias dinâmicas)

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

Etapa 2: seu 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" />

Etapa 3: em sua Atividade / Fragmento, sempre que houver guias.

/**
     * 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
fonte
Isso funcionou apenas com mais de uma guia, se tivermos apenas uma guia, a guia não preencherá o layout da guia. Para resolver esse problema, adicionei app: tabMaxWidth = "1000dp" e funcionou.
jzeferino
Isso funcionou melhor para mim. Na minha classe de layout de guia personalizada, substituí addTabe defino o peso de cada guia conforme ela foi adicionada. override fun addTab(tab: Tab, position: Int, setSelected: Boolean) { super.addTab(tab, position, setSelected) allotEachTabWithEqualWidth() }
Justin Lee
15

Para forçar as guias a ocuparem toda a largura (divididas em tamanhos iguais), aplique o seguinte à TabLayoutexibição:

TabLayout tabLayout = (TabLayout) findViewById(R.id.your_tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
Jon Cairns
fonte
2
Apenas informando às pessoas que isso não funciona se o seu TabLayoutestiver definido app:tabMode=“scrollable”, resultará no comprimento fixo das guias (as palavras longas serão quebradas) e as guias não serão mais deslizadas, essencialmente tornando as guias "fixas" novamente.
Sakiboy 24/08/19
5

Isso é útil, você deve tentar

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

trabalhe para mim. Isso também temxmlns:app="http://schemas.android.com/apk/res-auto"

Cam Hùng Huỳnh
fonte
3

Para mim, o código a seguir funcionou e foi suficiente.

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

Verifique o código abaixo para soluções.

Abaixo está o código do 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" />

Observe que, para a contagem dinâmica de guias, não se esqueça de chamar 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;
    }
}

Referência retirada de https://medium.com/@elsenovraditya/set-tab-minimum-width-of-scrollable-tablayout-programmatically-8146d6101efe

Kuldeep Sakhiya
fonte
2

Solução para Scrollable (Kotlin)

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

Em Kotlin:

No meu caso, se menos de 3 guias alocarem espaço igual.

Nota: Se a condição é conforme sua exigência

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

Por que todo esse trabalho agitado? Basta colocar o app:tabMode="scrollable"seu TabLayout em XML. É isso aí.

insira a descrição da imagem aqui

Ali Akram
fonte
1
E se houver 3 abas? que não cabe à tela (guias são dinâmicas que estão vindo de API servidor) guias contagem conhecido em tempo de execução ..
Ram Prakash Bhat
Em seguida, você pode definir programaticamente como este tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);Também é apenas uma propriedade a ser definida para tabLayout, não importa quantas guias você esteja adicionando, estática ou dinâmica.
Ali Akram
Ele fará a largura da guia de acordo com o tamanho do texto. Verifique minha resposta editada com a imagem.
Ali Akram
Ya em que o modo de guia caso é SCROLLABLE então no final u vai ver isso é espaço vazio parecer estranho
Ram Prakash Bhat
1

Na minha variante desse problema, eu tinha três guias de tamanho moderado que não estavam ocupando toda a largura dos tablets. Eu não precisava que as guias fossem roláveis ​​nos tablets, pois os tablets são grandes o suficiente para exibir as guias juntas sem necessidade de rolagem. Mas eu precisava que as guias fossem roláveis ​​nos telefones, pois os telefones são pequenos demais para exibir todas as guias juntas.

A melhor solução no meu caso foi adicionar um res/layout-sw600dp/main_activity.xmlarquivo, onde o TabLayout relevante poderia ter app:tabGravity="fill"e app:tabMode="fixed". Mas no meu regular res/layout/main_activity.xml, eu deixei de fora app:tabGravity="fill"e app:tabMode="fixed", em app:tabMode="scrollable"vez disso.

CKP78
fonte
-1

Observe que você também precisa definir

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

para preencher todo o espaço

Andrew Barabash
fonte
Bem-vindo ao Stack Overflow. Por favor, faça o passeio . Este é um site de perguntas e respostas, não um fórum de discussão. Esta seção é apenas para respostas completas. Depois de ganhar 50 pontos de reputação, perguntando e respondendo, você poderá comentar as perguntas e respostas de outros usuários .
Chris