BottomNavigationView mostra sempre sia le icone che le etichette di testo


125

Sto usando android.support.design.widget.BottomNavigationView dalla versione 25 della libreria di supporto alla progettazione

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

Quando sono presenti solo tre azioni in @ menu / bottom_navigation_main, vengono sempre visualizzate sia le icone che le etichette di testo.

Qual è il modo per visualizzare sempre sia le icone che le etichette di testo quando ci sono più di tre azioni.


Nel tuo menu bottom_navigation_main.xml, se hai android: showAsAction = "ifRoom" cambialo in android: showAsAction = "sempre" per ogni elemento.
Shashank Udupa

No, non ha funzionato. l'avevo provato prima.
Sviluppatore Android

Puoi mostrare il tuo file xml del menu
Shashank Udupa

"<? xml version =" 1.0 "encoding =" utf-8 "?> <menu xmlns: android =" schemas.android.com/apk/res/android "xmlns: app =" schemas.android.com/apk/ res-auto "> <item android: id =" @ + id / action_favorites "app: showAsAction =" always "/> <item android: id =" @ + id / action_schedules "app: showAsAction =" always "/> < item android: id = "@ + id / action_music" app: showAsAction = "always" /> <item android: id = "@ + id / account" android: enabled = "true" app: showAsAction = "always" /> </menu> "
Sviluppatore Android

4
place app: labelVisibilityMode = "labeled" in BottomNavigationView.
Shrawan

Risposte:


327

Per chiunque sia ancora alla ricerca di una soluzione e non voglia fare affidamento su librerie di terze parti o riflessione di runtime, BottomNavigationView in Support Library 28 / Jetpack supporta nativamente la presenza di un'etichetta di testo.

Questo è il metodo che stai cercando.

O in XML, app:labelVisibilityMode="labeled"


quale versione della libreria mi serve?
DaniloDeQueiroz

libreria di supporto 28-
alpha1

Puoi anche cambiare la modalità di visibilità in "auto" per mostrare il testo dell'icona solo quando viene premuto / focalizzato. Codice: app: labelVisibilityMode = "auto"
Kenny Dabiri

Tu sei l'uomo! Grazie, funziona con l'ultima versione di Material Library.
sud007

68

AGGIORNAMENTO DALL'8 maggio 2018

Puoi usare app:labelVisibilityMode="labeled" direttamente in<android.support.design.widget.BottomNavigationView />

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

Non hai bisogno di questa soluzione lunga sotto.

RISPOSTA PRECEDENTE

Ho avuto un comportamento strano con BottomNavigationView. Quando stavo selezionando un elemento / frammento in esso, il frammento spinge BottomNavigationView un po 'più in basso, quindi il testo di BottomNavigationView va sotto lo schermo, quindi solo le icone erano visibili e il testo viene nascosto quando si fa clic su qualsiasi elemento.

Se stai affrontando questo strano comportamento, ecco la soluzione. Basta rimuovere

android:fitsSystemWindows="true"

nel layout radice del frammento. Basta rimuovere questo e boom! BottomNavigationView funzionerà bene, ora può essere mostrato con testo e icona. Avevo questo nella mia radice CoordinatorLayout del frammento.

Inoltre, non dimenticare di aggiungere

BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

nella tua attività per disabilitare la modalità cambio.

Ecco quella classe:

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

Questo in combinazione con la risposta di STAR_ZERO ha risolto il mio problema!
Christopher Smit

Nella chiamata che hai disableShiftModee in classe removeShiftMode. A parte questa piccola discrepanza, la tua risposta ha risolto il problema per me. Ora ho cinque voci di menu senza spostamento e con testo + icona. Grazie molto molto!
Yamakuzure

Perfetto. Quando sono presenti più di 3 elementi nella navigazione inferiore di, viene visualizzata una modalità di spostamento. Usando questo, puoi disabilitare lo spostamento e quindi tutte le icone con il testo appaiono contemporaneamente.
Kishor Bikram Oli

1
Questa è un'API senza restrizioni e non funziona con la libreria di supporto versione 28. +. La risposta accettata da @shaishgandhi è un modo più corretto per farlo.
okarakose

19

È difficile nella versione 25.

Prova questo codice. Ma penso che non sia una buona soluzione.

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

In Android Studio, aggiungere un codice come questo: `` // noinspection RestrictedApi itemView.setShiftingMode (false); // noinspection RestrictedApi itemView.setChecked (false); ``
Jiezhi

4
è ancora sposta gli articoli
CodeToLife

1
Perfetto !! visualizza sia l'icona che il testo. Ma la modalità di cambio (falso) non funziona.
Minkoo

Questo in combinazione con la risposta di KishanSolanki124 ha risolto il mio problema!
Christopher Smit

11

Ecco una funzione di estensione di Kotlin che combina la soluzione @STAR_ZERO e @ 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)
        }
    }
}

Per usarlo:

myBottomNavigation.disableShiftMode()

10

Vuoi questo effetto?

Clicca qui per visualizzare l'immagine

In tal caso, ti ho consigliato di provare BottomNavigationViewEx


1
La tua libreria è un lavoro buono e impressionante Ma stavo cercando di ottenere questa funzionalità utilizzando la libreria di progettazione 25.0.0 Sfortunatamente è contro la pratica di progettazione di
Android

Ciò non è contro le specifiche di Material Design, secondo la "Barra di navigazione inferiore fissa" nei documenti . Inoltre, i miei ringraziamenti personali per aver condiviso questa fantastica libreria.
Serg de Adelantado

1
Questo è contro le specifiche di Material Design. Se leggi il documento che hai fornito, vedrai che dice esplicitamente "Se ci sono quattro o cinque azioni, mostra le viste inattive solo come icone".
Felipe

8

Puoi usarlo per mostrare sia il testo che le icone su BottomNevigationView

app:labelVisibilityMode="labeled"

Se lo stai utilizzando, sarai in grado di visualizzare sia l'icona che il testo

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

6

Puoi utilizzare app: labelVisibilityMode = "labeled" direttamente in

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

5

nella classe BottomNavigationView c'è un campo BottomNavigationMenuView e in BottomNavigationMenuView c'è un campo BottomNavigationItemView [], che sono gli elementi nella barra inferiore.

Diciamo che n è il numero di elementi, BottomNavigationMenuView chiamerà BottomNavigationItemView.setShiftingMode (n> 3) su ogni membro della matrice BottomNavigationItemView []. Questa funzione decide il comportamento (mostra il titolo sempre o solo al momento della selezione).

quindi il modo per mostrare sempre i titoli è provare a chiamare questo metodo e puoi usare la reflection per accedere ai campi privati.

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

Questo è molto buono, dobbiamo solo assicurarci che BottomNavigationMenuView non si sposti. -> f = menuView.getClass (). getDeclaredField ("mShiftingMode"); f.setAccessible (true); f.setBoolean (menuView, false);
stephane k.

4

Per mostrare i titoli fino in fondo. Prova questo codice 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)
    }
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.