BottomNavigationView muestra íconos y etiquetas de texto en todo momento

125

Estoy usando android.support.design.widget.BottomNavigationView de la biblioteca de soporte de diseño versión 25

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

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottomBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="center"
        app:itemBackground="@color/colorPrimary"
        app:menu="@menu/bottom_navigation_main"
        android:forceHasOverlappingRendering="true"/>

Cuando solo hay tres acciones en @ menu / bottom_navigation_main, muestra íconos y etiquetas de texto en todo momento.

¿Cuál es la manera de mostrar iconos y etiquetas de texto en todo momento cuando hay más de tres acciones?

Desarrollador de Android
fuente
En su menú bottom_navigation_main.xml, si tiene android: showAsAction = "ifRoom" cámbielo a android: showAsAction = "always" para cada elemento.
Shashank Udupa
No, no funcionó. Lo había intentado antes.
Desarrollador de Android el
¿Puedes mostrar tu archivo xml del menú
Shashank Udupa
'<? xml version = "1.0" encoding = "utf-8"?> <menu xmlns: android = " schemas.android.com/apk/res/android " xmlns: app = " schemas.android.com/apk/ aplicación res-auto "> <item android: id =" @ + id / action_favorites ": showAsAction =" always "/> <item android: id =" @ + id / action_schedules "app: showAsAction =" always "/> < aplicación android: id = "@ + id / action_music": showAsAction = "always" /> <item android: id = "@ + id / account" android: enabled = "true" aplicación: showAsAction = "always" /> </menu> '
Desarrollador de Android el
44
aplicación de lugar: labelVisibilityMode = "etiquetado" en BottomNavigationView.
Shrawan

Respuestas:

326

Para cualquiera que todavía esté buscando una solución y no quiera depender de bibliotecas de terceros o reflexión en tiempo de ejecución, BottomNavigationView en Support Library 28 / Jetpack admite de forma nativa tener siempre etiquetas de texto.

Este es el método que estás buscando.

O en XML, app:labelVisibilityMode="labeled"

shaishgandhi
fuente
¿Qué versión de biblioteca necesito?
DaniloDeQueiroz
biblioteca de soporte 28-alpha1 +
shaishgandhi
También puede cambiar el modo de visibilidad a "automático" para mostrar el texto del icono cuando se presiona / enfoca solamente. Código: aplicación: labelVisibilityMode = "auto"
Kenny Dabiri
¡Tu eres el hombre! Gracias, esto funciona con la última versión de la Biblioteca de materiales.
sud007
68

ACTUALIZACIÓN DEL 8 DE MAYO DE 2018

Puedes usar app:labelVisibilityMode="labeled" directamente en<android.support.design.widget.BottomNavigationView />

Fuente: https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode

No necesito esto debajo de una solución larga.

RESPUESTA ANTERIOR

Tuve un comportamiento extraño con BottomNavigationView. Cuando estaba seleccionando cualquier elemento / fragmento en él, el fragmento empuja BottomNavigationView un poco más abajo, por lo que el texto de BottomNavigationView va debajo de la pantalla, por lo que solo los iconos estaban visibles y el texto se oculta al hacer clic en cualquier elemento.

Si se enfrenta a ese comportamiento extraño, entonces esta es la solución. Solo eliminar

android:fitsSystemWindows="true"

en su diseño raíz de fragmento. Solo elimina esto y ¡boom! BottomNavigationView funcionará bien, ahora se puede mostrar con texto e ícono. Tenía esto en mi raíz CoordinatorLayout of fragment.

Tampoco olvides agregar

BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

en su actividad para desactivar el modo de cambio.

Aquí está esa clase:

public class BottomNavigationViewHelper {

    @SuppressLint("RestrictedApi")
    public static void removeShiftMode(BottomNavigationView view) {
        //this will remove shift mode for bottom navigation 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);
                // set once again checked value, so view will be updated
                item.setChecked(item.getItemData().isChecked());
            }

        } catch (NoSuchFieldException e) {
            Log.e("ERROR NO SUCH FIELD", "Unable to get shift mode field");
        } catch (IllegalAccessException e) {
            Log.e("ERROR ILLEGAL ALG", "Unable to change value of shift mode");
        }
    }
}
Kishan Solanki
fuente
¡Esto en combinación con la respuesta de STAR_ZERO resolvió mi problema!
Christopher Smit
En la llamada que tienes disableShiftMode, y en la clase removeShiftMode. Aparte de esa pequeña discrepancia, su respuesta resolvió el problema para mí. Ahora tengo cinco elementos de menú sin desplazamiento y con texto + icono. Gracias muy mucho!
Yamakuzure
Perfecto. Cuando tiene más de 3 elementos en su navegación inferior, aparece un modo de cambio. Con esto, puede deshabilitar ese desplazamiento y, por lo tanto, todos los iconos con texto aparecen a la vez.
Kishor Bikram Oli
1
Esta es una API sin restricciones y no funciona en la biblioteca de soporte versión 28. +. La respuesta @shaishgandhi aceptada es la forma más adecuada de hacerlo.
okarakose
19

Es difícil en la versión 25.

Prueba este código. Pero creo que no es una buena solución.

BottomNavigationView navigationView = (BottomNavigationView) findViewById(R.id.bottomBar);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
    BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(i);
    itemView.setShiftingMode(false);
    itemView.setChecked(false);
}
STAR_ZERO
fuente
En Android Studio, debería agregar un código como este: `` `// noinspection RestrictedApi itemView.setShiftingMode (false); // noinspection RestrictedApi itemView.setChecked (false); `` ``
Jiezhi.G
44
todavía se desplaza artículos
CodeToLife
1
Perfecto !! muestra ícono y texto. Pero el modo de cambio (falso) no funciona.
Minkoo
¡Esto en combinación con la respuesta de KishanSolanki124 resolvió mi problema!
Christopher Smit
11

Aquí hay una función de extensión de Kotlin que combina la solución @STAR_ZERO y @ KishanSolanki124.

fun BottomNavigationView.disableShiftMode() {
    val menuView = getChildAt(0) as BottomNavigationMenuView

    menuView.javaClass.getDeclaredField("mShiftingMode").apply {
        isAccessible = true
        setBoolean(menuView, false)
        isAccessible = false
    }

    @SuppressLint("RestrictedApi")
    for (i in 0 until menuView.childCount) {
        (menuView.getChildAt(i) as BottomNavigationItemView).apply {
            setShiftingMode(false)
            setChecked(false)
        }
    }
}

Para usarlo:

myBottomNavigation.disableShiftMode()
chetbox
fuente
10

¿Quieres este efecto?

Haga clic aquí para ver la imagen.

Si es así, te recomendé que pruebes BottomNavigationViewEx

ittianyu
fuente
1
Su biblioteca es un trabajo bueno e impresionante Pero estaba buscando lograr esta funcionalidad usando la biblioteca de diseño 25.0.0 Desafortunadamente, está en contra de la práctica de diseño de
Android
Esto no está en contra de las especificaciones de Diseño de materiales, de acuerdo con la "Barra de navegación inferior fija" en los documentos . Además, mi agradecimiento personal por compartir esta increíble biblioteca.
Serg de Adelantado
1
Esto ES contra las especificaciones de diseño de materiales. Si lee el documento que proporcionó, verá que explícitamente dice "Si hay cuatro o cinco acciones, muestre las vistas inactivas solo como iconos".
Felipe
8

Puede usar esto para mostrar texto e íconos en BottomNevigationView

app:labelVisibilityMode="labeled"

Si está utilizando esto, podrá ver tanto el icono como el texto.

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/bottom_navigation_view"
    android:layout_alignParentBottom="true"
    app:menu="@menu/bottom_navigation_menu"/>
Kumar Ajay AK
fuente
6

Puede usar la aplicación: labelVisibilityMode = "etiquetado" directamente en

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:labelVisibilityMode="labeled"
        android:elevation="8dp"
        android:layout_alignParentBottom="true"
        app:itemBackground="@drawable/bottom_navi"
        app:itemTextColor="@color/white"
        app:itemIconTint="@color/white"
        app:menu="@menu/bottom_nav_menu_managment" />
kishan verma
fuente
5

en la clase BottomNavigationView hay un campo BottomNavigationMenuView y en BottomNavigationMenuView hay un campo BottomNavigationItemView [], que son los elementos en la barra inferior.

Digamos que n es el número de elementos, BottomNavigationMenuView llamará a BottomNavigationItemView.setShiftingMode (n> 3) en cada miembro de la matriz BottomNavigationItemView []. Esta función decide el comportamiento (mostrar título siempre o solo después de la selección).

así que la forma de mostrar siempre los títulos es intentar llamar a este método y puede usar la reflexión para acceder a los campos privados.

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


//  get the private BottomNavigationMenuView field 
        Field f = null;
        try {
            f = bottomNavigationView.getClass().getDeclaredField("mMenuView");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        f.setAccessible(true);
        BottomNavigationMenuView menuView=null;
        try {
             menuView = (BottomNavigationMenuView) f.get(bottomNavigationView); 
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

//  get the private BottomNavigationItemView[]  field 
        try {
            f=menuView.getClass().getDeclaredField("mButtons");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        f.setAccessible(true);
        BottomNavigationItemView[] mButtons=null;
        try {
            mButtons = (BottomNavigationItemView[]) f.get(menuView); 
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }


        for(int i=0;i<mButtons.length;i++){
            mButtons[i].setShiftingMode(false);
            mButtons[i].setChecked(true);
        }
wei wang
fuente
Esto es muy bueno, solo necesitamos asegurarnos de que BottomNavigationMenuView tampoco se mueva. -> f = menuView.getClass (). getDeclaredField ("mShiftingMode"); f.setAccessible (verdadero); f.setBoolean (menuView, falso);
stephane k.
4

Para mostrar los títulos hasta el final. Prueba este código de Kotlin:

@SuppressLint("RestrictedApi")
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_ofree)

    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)

    val menuView = navigation.getChildAt(0) as BottomNavigationMenuView
    for (i in 0 until menuView.childCount) {
        val itemView = menuView.getChildAt(i) as BottomNavigationItemView
        itemView.setShiftingMode(false)
        itemView.setChecked(false)
    }
}
Harry Zhang
fuente
1

Alternativa a BottomNavigationViewEx : BottomBar

Mateusz Budzisz
fuente