BottomNavigationView com mais de 3 itens: o título da guia está oculto

85

Estou usando BottomNavigationView com o Android Support Desing Library 25. Mas quando eu alterno as guias, o título da outra guia fica oculto. Mas não há problema de esconder a visão de navegação inferior real. Mas o meu está se escondendo.

MyBottomNavigation

Mas eu quero que pareça assim. Alguma ideia de fazer isso? o que estou perdendo?

ActualBottomNavigation

Aqui está o meu código:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.yunus.ototakip.MainActivity">

<FrameLayout
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/bottom_navigation"
    android:layout_alignParentTop="true">
</FrameLayout>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@color/beyaz"
    app:itemTextColor="@color/beyaz"
    app:menu="@menu/bottombar_menu" />

bottom_bar_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
 <item
android:id="@+id/bb_menu_arac"
android:enabled="true"
android:icon="@drawable/icon_car"
android:title="@string/araclarim"
app:showAsAction="ifRoom" />
 <item
android:id="@+id/bb_menu_yakin"
android:enabled="true"
android:icon="@drawable/icon_yer"
android:title="@string/yakinimdakiler"
app:showAsAction="ifRoom" />
  <item
android:id="@+id/bb_menu_yaklasan"
android:enabled="true"
android:icon="@drawable/icon_takvim"
android:title="@string/yaklasanlar"
app:showAsAction="ifRoom" />

<item
    android:id="@+id/bb_menu_ipucu"
    android:enabled="true"
    android:icon="@drawable/icon_ipucu"
    android:title="@string/ipuclari"
    app:showAsAction="ifRoom" />
 </menu>
Yunus Haznedar
fonte
você tentou em app:showAsAction="alwaysvez deifRoom
Yassine BELDI
Eu tentei, mas ainda está escondido
Yunus Haznedar
1
verifique aqui stackoverflow.com/questions/36032177/…
Yassine BELDI
1
@YunusHaznedar se o item for maior que 3, o texto sempre ficará oculto ...
Shashank Verma
1
Olá, @DanXPrado obrigado por compartilhar a solução. Eu marquei sua resposta como aceita. Boa codificação.
Yunus Haznedar de

Respostas:

143

A solução usando reflexão não funciona mais porque o campo mShiftingMode foi removido.

Existe uma maneira fácil de fazer isso agora: Use a Biblioteca de Suporte 28 ou superior e apenas adicione app:labelVisibilityMode="labeled"à sua BottomNavigationViewdeclaração XML.

Espero que ajude.

Danilo Prado
fonte
Trabalhando como um campeão, mas como torná-lo rolável circular?
Shailendra Madda
@ShylendraMadda Eu sugiro que você poste isso como uma nova pergunta, já que não está relacionado a esta pergunta.
Danilo Prado
1
Como este não é o comportamento padrão ... Perdi algumas horas com app: showAsAction, android: visible, android: enabled e um monte de outros hacks. Obrigado!
Dinamarquês Khan
94

ATUALIZAR

removeShiftMode () não é mais necessário, pois na biblioteca de suporte 28.0.0-alpha1 podemos agora adicionar Labels .

Em XML:

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />

Para alteração programada:

mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); 

Para que isso funcione: atualize a biblioteca de suporte de design para 28.0.0-alpha1

Aqui está uma boa leitura

PARA A BIBLIOTECA DE SUPORTE PARA IDOSOS:

em seu. bottom_bar_menu.xmlAltere o showAsActionatributo

<item android:id="@id/menu_item"
android:title="text"
android:icon="@drawable/drawable_resource_name"
android:showAsAction="always|withText" />

em build.gradle:

compile 'com.android.support:design:25.3.1'

NAVEGAÇÃO INFERIOR VISUALIZE MAIS DE 3 ITENS: use o removeShiftMode()método

em BottomNavigationViewHelper.javauso:

import android.annotation.SuppressLint;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import java.lang.reflect.Field;

    public class BottomNavigationViewHelper {
        @SuppressLint("RestrictedApi")
        public static void removeShiftMode(BottomNavigationView view) {
            BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
            try {
                Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
                shiftingMode.setAccessible(true);
                shiftingMode.setBoolean(menuView, false);
                shiftingMode.setAccessible(false);
                for (int i = 0; i < menuView.getChildCount(); i++) {
                    BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                    //noinspection RestrictedApi
                    item.setShiftingMode(false);
                    // set once again checked value, so view will be updated
                    //noinspection RestrictedApi
                    item.setChecked(item.getItemData().isChecked());
                }
            } catch (NoSuchFieldException e) {
                Log.e("BottomNav", "Unable to get shift mode field", e);
            } catch (IllegalAccessException e) {
                Log.e("BottomNav", "Unable to change value of shift mode", e);
            }
        }
    }

Chame-o usando:

BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_navigation);
BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

Isso desabilitará a animação de deslocamento do texto do título e permitirá que o texto seja exibido.

rafsanahmad007
fonte
2
Não, ainda está se escondendo. Tentei "sempre" e "sempre | com texto"
Yunus Haznedar
1
um dos títulos do seu item é grande está causando o bloqueio da visão dos outros? tente com títulos pequenos e imagens
desenhadas
1
veja esta linha no tutotrial que você está seguindoIt’s important to note that the maximum number of items we can display is 5. This may change at any point, so it’s important to check this by using the getMaxItem() method provided by the BottomNavigationView class rather than hard-coding the value yourself.
rafsanahmad007
1
ótima resposta, obrigado
Hamza Abdullah
2
A solução de reflexão funciona muito bem com.android.support:design:25.4.0, mas falha com.android.support:design:26.1.0, então reverto um pouco o SDK de destino e a versão das dependências.
Evi Song
10

Após escanear o código-fonte de BottomNavigationView, encontro

mShiftingMode = mMenu.size() > 3;

na linha 265 BottomNavigationMenuView.java , significa que enquanto o tamanho do menu for maior que 3, o título da guia ficará oculto. Então, se você quiser mostrar o título da guia, você só precisa obter o código do build e alterar para o seguinte.

mShiftingMode = mMenu.size() > 5;

PS: a contagem máxima de guias de BottonNavigationView deve estar entre 3 e 5. Você pode obter o código em BottomNavigationViewNew insira a descrição da imagem aqui

ScuAdam
fonte
Eu tenho meu próprio CustomBottomView que estende BottomNavigationView. Existe uma maneira de definir essa propriedade?
JPM
1
Não vejo a linha de "BottomNavigationMenuView" que é sobre o limite de 3 guias. Talvez o código tenha mudado?
desenvolvedor Android de
8

Criar classe BottomNavigationViewHelper

import android.annotation.SuppressLint;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.util.Log;
import java.lang.reflect.Field;
public class BottomNavigationViewHelper {
    @SuppressLint("RestrictedApi")
    public static void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
if(menuView.getChildCount()<6)
           {
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
         }
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", "Unable to change value of shift mode", e);
        }
    }
}   

Ligar

    BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_navigation);
    BottomNavigationViewHelper.disableShiftMode(bottomNavigationView); 
Ram Krishna
fonte
1
Tem SuppressLint que resolve o problema de annoation de API restrita
code4j
3

Função de extensão Kotlin:

@SuppressLint("RestrictedApi")
fun BottomNavigationView.removeShiftMode(){
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView.javaClass.getDeclaredField("mShiftingMode")
        shiftingMode.isAccessible = true
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.isAccessible = false
        for (i in 0 until menuView.childCount) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.itemData.isChecked)
        }
    } catch (e: NoSuchFieldException) {
        e.printStackTrace()
        Timber.tag("BottomNav").e( e, "Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.tag("BottomNav").e( e, "Unable to change value of shift mode")
    }
}
jpardogo
fonte
Obrigado, senhor. Muito apreciado.
Yunus Haznedar
1
item.setShiftingMode(false)é agoraitem.setShifting(false)
Sim,
2

Eu praticamente usei a resposta rafsanahmad007, mas traduzi para Kotlin. Deixe-me compartilhar para os futuros errantes

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
        shiftingMode.setAccessible(true)
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.setAccessible(false)
        for (i in 0..(menuView.childCount - 1)) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.getItemData().isChecked())
        }
    } catch (e: NoSuchFieldException) {
        Timber.e("Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.e("Unable to change value of shift mode")
    }
}
Karma Maker
fonte
1
Esta solução não é mais válida, a solução aceita está correta por @DanXPrado
jpardogo
Obrigado por me avisar
Karma Maker
1

Uma coisa a ser observada, embora não se aplique neste caso.

Esse padrão pode ser usado quando você tem entre 3 e 5 destinos de nível superior para navegar.

Para ativar a exibição do título do ícone, faça o seguinte:

  1. Certifique-se de que o XML do seu item de menu (bottom_navigation_menu) esteja estruturado da seguinte forma: -

    <item
        android:id="@+id/action_home"
        android:enabled="true"
        android:icon="@drawable/ic_action_home"
        android:title="HOME"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_favourites"
        android:enabled="true"
        android:icon="@drawable/ic_action_favourite"
        android:title="FAVOURITES"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_basket"
        android:enabled="true"
        android:icon="@drawable/ic_action_basket"
        android:title="BASKET"
        app:showAsAction="ifRoom"/>
    

  2. Adicione o seguinte ao aplicativo de código BottomNavigationView: labelVisibilityMode = "label"

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@android:color/white"
    app:itemIconTint="@android:color/black"
    app:itemTextColor="@android:color/black"
    app:menu="@menu/bottom_navigation_menu"
    app:labelVisibilityMode="labeled"/>

George
fonte
0

Isso funciona para mim na API 26:

 navigation = (BottomNavigationView) view.findViewById(R.id.bottom_navigation);


     try{disableShiftMode(navigation);}catch(Exception ew){}

Faça este método em sua atividade ou fragmento onde deseja chamar:

 @SuppressLint("RestrictedApi")
public static void disableShiftMode(BottomNavigationView view) {
    BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
    try {
        Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
        shiftingMode.setAccessible(true);
        shiftingMode.setBoolean(menuView, false);
        shiftingMode.setAccessible(false);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            item.setShiftingMode(false);

            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {

    } catch (IllegalAccessException e) {

    }
}
Istiyak
fonte
0

Você pode usar isso para mostrar texto e ícones em BottomNevigationView para 3 a 5 itens e parar de mudar.

 app:labelVisibilityMode="labeled"

Mas você enfrentará um problema de corte de texto longo no BottmNevigationView para 5 itens. para isso, encontrei uma boa solução para interromper o deslocamento de texto e também de ícones de BottomNevigationView. Você também pode interromper o deslocamento do texto, bem como dos ícones em BottomNevigationView. Snipshots de código são fornecidos aqui.

1. Adicione alguma linha de código em BottomNevigationView como mostrado

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="@dimen/seventy_dp"
    android:layout_semitransparent="true"
    android:background="@color/colorBottomNev"
    android:showAsAction="always|withText"
    app:itemIconTint="@drawable/bottom_navigation_colors"
    app:itemTextColor="@drawable/bottom_navigation_colors"
    app:itemTextAppearanceActive="@style/BottomNavigationViewTextStyle"
    app:itemTextAppearanceInactive="@style/BottomNavigationViewTextStyle"
    app:menu="@menu/bottom_navigation_menu"
    app:labelVisibilityMode="labeled"/>

2. Adicione itens de menu da seguinte forma: -

 <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_catalogue"
        android:icon="@drawable/catalogue"
        android:title="@string/catalogue"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_contracts"
        android:icon="@drawable/contract"
        android:title="@string/contracts"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_prospects"
        android:icon="@drawable/prospect"
        android:title="@string/prospects"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_performance"
        android:icon="@drawable/performance"
        android:title="@string/performance"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_advance"
        android:icon="@drawable/advance"
        android:title="@string/advance"
        android:enabled="true"
        app:showAsAction="ifRoom" />

</menu>

3. Adicione este estilo no arquivo style.xml:

 <style name="BottomNavigationViewTextStyle">
            <item name="android:fontFamily">@font/montmedium</item>
            <item name="android:textSize">10sp</item>
            <item name="android:duplicateParentState">true</item>
            <item name="android:ellipsize">end</item>
            <item name="android:maxLines">1</item>
        </style>

4) Adicione estes na pasta Dimen

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <dimen name="design_bottom_navigation_text_size" tools:override="true">10sp</dimen>
    <dimen name="design_bottom_navigation_active_text_size" tools:override="true">10sp</dimen>
</resources>

Recebi ajuda por meio desses links e links . Você também pode obter ajuda estudando esses links. Isso me ajuda muito. Espero que também ajude você. Obrigado....

Rahul Kushwaha
fonte
0

correção rápida basta adicionar app: labelVisibilityMode = "label" em xml

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@drawable/bottom_navigation_color_selector"
    app:itemTextColor="@drawable/bottom_navigation_color_selector"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/menu_bottom_navigation" />

Nota

  implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
Mujahid Khan
fonte