BottomNavigationView con más de 3 elementos: el título de la pestaña se oculta


85

Estoy usando BottomNavigationView con el uso de Android Support Desing Library 25. Pero cuando cambio las pestañas, el título de la otra pestaña se oculta. Pero no hay ningún problema para ocultar la vista de navegación inferior real. Pero el mío se esconde.

MyBottomNavigation

Pero quiero que se vea así. ¿Alguna idea para hacer eso? ¿Qué me estoy perdiendo?

ActualBottomNavigation

Aquí está mi 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>

lo intentaste en app:showAsAction="alwayslugar deifRoom
Yassine BELDI

Lo intenté, pero todavía se esconde
Yunus Haznedar


1
@YunusHaznedar si el elemento es más de 3, el texto siempre se ocultará ...
Shashank Verma

1
Hola, @DanXPrado gracias por compartir la solución. He marcado tu respuesta como aceptada. Codificación feliz.
Yunus Haznedar

Respuestas:


139

La solución que usa la reflexión ya no funciona porque se eliminó el campo mShiftingMode.

Hay una manera fácil de hacerlo ahora: use Support Library 28 y simplemente agregue app:labelVisibilityMode="labeled"a su BottomNavigationViewdeclaración XML.

Espero eso ayude.


Trabajando como un campeón, pero ¿cómo hacerlo circular desplazable?
Shailendra Madda

@ShylendraMadda Te sugiero que publiques eso como una nueva pregunta ya que no está relacionada con esta pregunta.
Danilo Prado

1
¿Cómo no es este el comportamiento predeterminado? Perdí algunas horas con la aplicación: showAsAction, android: visible, android: enabled y un montón de otros trucos. ¡Gracias!
Danish Khan

94

ACTUALIZAR

removeShiftMode () ya no es necesario, ya que en la biblioteca de soporte 28.0.0-alpha1 ahora podemos agregar etiquetas .

En XML:

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

Para cambiar programáticamente:

mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); 

Para que esto funcione: actualice la biblioteca de soporte de diseño a 28.0.0-alpha1

Aquí hay una buena lectura

PARA BIBLIOTECA DE SOPORTE ANTIGUO:

en tu bottom_bar_menu.xml.Cambia el showAsActionatributo

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

en build.gradle:

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

NAVEGACIÓN INFERIORVER MÁS DE 3 ARTÍCULOS: removeShiftMode()método de uso

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

Llámalo usando:

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

Deshabilitará la animación de cambio del texto del título y permitirá que se muestre el texto.


2
No, todavía se esconde. Intenté "siempre" y "siempre | con texto"
Yunus Haznedar

1
¿El título de uno de nuestros elementos es grande está causando que la vista del otro se bloquee? pruebe con un título pequeño e imágenes
dibujables

1
vea esta línea en el tutorial que está siguiendoIt’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
gran respuesta, gracias
Hamza Abdullah

2
La solución de reflexión funciona bastante bien com.android.support:design:25.4.0, pero falla com.android.support:design:26.1.0, así que revierto un poco el SDK de destino y la versión de las dependencias.
Evi Song

10

Después de escanear el código fuente de BottomNavigationView, encuentro

mShiftingMode = mMenu.size() > 3;

en BottomNavigationMenuView.java línea 265, significa que mientras el tamaño del menú sea superior a 3, el título de la pestaña se ocultará. Entonces, si desea mostrar el título de la pestaña, solo necesita obtener el código de la compilación y cambiarlo a continuación.

mShiftingMode = mMenu.size() > 5;

PD: el recuento máximo de pestañas de BottonNavigationView debe estar entre 3 y 5. Puede obtener el código en BottomNavigationViewNew ingrese la descripción de la imagen aquí


Tengo mi propio CustomBottomView que extiende BottomNavigationView, ¿hay alguna forma de establecer esa propiedad en su lugar?
JPM

1
No veo la línea de "BottomNavigationMenuView" que es sobre el límite de 3 pestañas. ¿Quizás el código ha cambiado?
desarrollador de Android

8

Crear clase 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);
        }
    }
}   

Llamada

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

1
Tiene SuppressLint que resuelve el problema de la anotación restrictAPI
code4j

3

Función de extensión de 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")
    }
}

Gracias Señor. Muy apreciado.
Yunus Haznedar

1
item.setShiftingMode(false)es ahoraitem.setShifting(false)
Sim

2

Prácticamente utilicé la respuesta rafsanahmad007 pero la traduje a Kotlin. Déjame compartirlo para los futuros vagabundos.

@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")
    }
}

1
Esta solución ya no es válida, la solución aceptada es correcta por @DanXPrado
jpardogo

Gracias por hacérmelo saber
Karma Maker

0

Esto me funciona en API 26:

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


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

Haga este método en su Actividad o Fragmento donde desea llamar:

 @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) {

    }
}

0

Puede usar esto para mostrar texto e íconos en BottomNevigationView para 3 a 5 elementos y dejar de cambiar.

 app:labelVisibilityMode="labeled"

Pero enfrentará un problema de corte de texto largo en BottmNevigationView para 5 elementos. para eso, encontré una buena solución para detener el desplazamiento de texto, así como los iconos de BottomNevigationView. También puede detener el desplazamiento de texto y de iconos en BottomNevigationView. Aquí se proporcionan fragmentos de código.

1. Agregue esta línea de código en BottomNevigationView como se muestra

<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. Agregue elementos de menú de la siguiente manera: -

 <?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.Agregue este estilo en el archivo 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) Agregue estos en la carpeta 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>

Obtuve ayuda de estos enlaces y enlaces . También puede obtener ayuda estudiando estos enlaces. Esto me ayuda mucho. Espero que esto también lo ayude. Gracias....


0

arreglado rápido solo agregue la aplicación: labelVisibilityMode = "etiquetado" en 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'

0

Una cosa a tener en cuenta, aunque no se aplica en este caso.

Este patrón se puede utilizar cuando tiene entre 3 y 5 destinos de nivel superior para navegar.

Para permitir que se muestre el título del icono, haga lo siguiente:

  1. Asegúrese de que el elemento XML de su menú (bottom_navigation_menu) esté estructurado de la siguiente manera: -

    <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. Agregue lo siguiente a la aplicación de código BottomNavigationView: labelVisibilityMode = "labeldo"

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.