Come disabilitare la modalità shift BottomNavigationView?


146

BottomNavigationView non mostra il titolo del menu che è inattivo.

Come mostrare i titoli di tutti gli elementi di menu in bottomNavigationBar? Il problema è che nel mio caso è stato mostrato solo il titolo dell'elemento su cui si fa clic.

inserisci qui la descrizione dell'immagine


1
Possibile duplicato della nuova barra di navigazione inferiore
Radhey,

Ecco una risposta utile se si desidera rimuovere completamente qualsiasi animazione: stackoverflow.com/a/51052247/2352699
Fred Porciúncula,

Risposte:


330

L'implementazione di BottomNavigationViewha condizione: quando ci sono più di 3 elementi, utilizzare la modalità shift.

Al momento non è possibile modificarlo tramite l'API esistente e l'unico modo per disabilitare la modalità shift è utilizzare la riflessione.

Avrai bisogno della classe di aiuto:

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

Quindi applica il disableShiftModemetodo sul tuo BottomNavigationView, ma ricorda se stai gonfiando la vista del menu dal tuo codice, devi eseguirlo dopo il gonfiamento.

Esempio di utilizzo:

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

PS.

Ricorda, dovrai eseguire questo metodo ogni volta che cambi voci di menu nel tuo BottomNavigationView.

AGGIORNARE

Devi anche aggiornare il file di configurazione di proguard (es. Proguard-rules.pro), il codice sopra usa la riflessione e non funzionerà se proguard offusca il mShiftingModecampo.

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}

Grazie Muhammad Alfaifi per aver segnalato questo problema e fornito lo snippet .

AGGIORNAMENTO 2

Come ha sottolineato Jolanda Verhoef, la nuova libreria Support ( 28.0.0-alpha1) e anche la nuova libreria Material Components ( 1.0.0-beta01) offre una proprietà pubblica che può essere utilizzata per manipolare la modalità di spostamento su 3 voci di menu.

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:labelVisibilityMode="labeled"
    ... 
/>

Nella libreria Componenti materiali si applica anche se ci sono 5 voci di menu.

AGGIORNAMENTO 3

Come ha sottolineato anche @ThomasSunderland, è possibile impostare questa proprietà su false app:itemHorizontalTranslation="false"senza Enabledpostfix per disabilitare lo spostamento dell'animazione.

puoi consultare la guida completa per lo styling di BottomNavigation qui


10
**** Proguard :(
Muhammad Alfaifi,

17
Il campo verrà offuscato, quindi non c'è modo di cambiarne il valore se non lo si esclude dal file delle regole di
proguard

8
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {booleano mShiftingMode; }
Muhammad Alfaifi,

8
A volte, mi chiedo davvero perché Google costringa a visualizzare implementazioni sugli sviluppatori. Mentre ci sono 4 opzioni sull'app Google+ stessa, questa semplice funzione avrebbe dovuto essere accessibile tramite una semplice funzione se disponibile! Problema simile era presente con TabLayout, che è stato risolto molto più tardi nella libreria di supporto. Grazie per la soluzione alternativa a Original Replier e @MuhammadAlfaifi per il miglioramento.
sud007,

19
La nuova libreria di supporto (28.0.0-alpha1) supporta la modifica di questo comportamento tramite l'app: labelVisibilityMode = "labeled"
Jolanda Verhoef

50

Dalla libreria di supporto 28.0.0-alpha1:

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

1
Sto usando questa versione della libreria di supporto ma sto ancora ricevendo un errore su "labelVisibilityMode" non trovato.
Sagar Maiyad,

1
Funziona correttamente. Non c'è bisogno di andare per la riflessione. Grazie
mille

1
@Riser assicurati di app:non utilizzareandroid:
Carson Holzheimer il

28

Per disabilitare l'animazione del testo puoi anche usarlo nel tuo file dimens.xml:

<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>

Potrebbe anche essere necessario aggiungere questo nel manifest:

tools:override="true"

non funziona. Credo di doverlo aggiungere in /values/dimens.xml?
Rohan Kandwal,

10
@RohanKandwal deve aggiungeretools:override="true"
Boy

@Boy Grazie, ci proverò.
Rohan Kandwal,

cambia solo la dimensione del testo.
The Dude,

Devo solo inserire questo nel mio file dimens.xml:<dimen name="design_bottom_navigation_active_text_size" tools:ignore="PrivateResource">12sp</dimen>
Fernando Barbosa,

22

Ora puoi usare app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"in28-alpha

  • labeled manterrà visibili tutte le etichette.
  • unlabeled mostrerà solo icone.
  • selected mostrerà solo l'etichetta per l'elemento selezionato e sposta gli articoli.
  • autosceglierà etichettato o selezionato in base al numero di articoli che hai. etichettato per 1-3 articoli e selezionato per 3+ articoli.

1
grazie Lunkie! Questa è la soluzione migliore e più semplice per me
Gregriggins36,

Dove aggiungere questa riga di codice. Ho provato ad aggiungere ma c'è un errore non trovato.
Abdulwahid,

@Abdulwahid puoi aggiungerlo nel file XML della barra di navigazione in basso una volta che hai la libreria di supporto 28 o successiva
Aidan Laing,

@Lunkie grazie ora è chiaro una volta che la libreria di supporto 28
Abdulwahid,

17

La risposta di Przemysław a Kotlin come funzione di estensione

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.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) {
        Log.e(TAG, "Unable to get shift mode field", e)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "Unable to change value of shift mode", e)
    }
}

Utilizzo (con estensioni Android Kotlin):

bottom_navigation_view.disableShiftMode()

Funzionando per Kotlin. perché dobbiamo usare questa annotazione @SuppressLint ("RestrictedApi") puoi spiegare pls?
Ranjith Kumar,

11

Per me va bene

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

o

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

il mio stava funzionando bene fino a target = 27 ma da target = 28, è rotto, il testo non viene più visualizzato. Ma setLabelVisibilityMode fa il trucco per me, ora funziona come un incantesimo
joke4me

10

Per disabilitare l'animazione del testo e ridurre la dimensione del carattere, utilizzalo nel tuo file dimens.xml:

<dimen name="design_bottom_navigation_text_size">10sp</dimen> 
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>

Si può Navigate-> File...> design_bottom_navigation_item.xmlper vedere che non c'è altro modo.
Arekolek,

6

AGGIORNARE

in Android sdk versione 28 e successive sono stati cambiati item.setShiftingMode(false)initem.setShifting(false)

Inoltre hanno rimosso il campo mShiftingMode

Quindi l'utilizzo sarà

 BottomNavigationHelper.removeShiftMode(bottomNav);
 bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);


 private static final class BottomNavigationHelper {
    @SuppressLint("RestrictedApi")
    static void removeShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            //noinspection RestrictedApi
            item.setShifting(false);
            item.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

            // set once again checked value, so view will be updated
            //noinspection RestrictedApi
            item.setChecked(item.getItemData().isChecked());
        }
    }
}

puoi usare questo codice qui sotto. @SuppressLint ( "RestrictedApi") divertente removeShiftMode (vista: BottomNavigationView) {val = menuView view.getChildAt (0) come BottomNavigationMenuView menuView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED menuView.buildMenuView ()}
Profonda P

5

Come altri hanno sottolineato, poiché la libreria di supporto 28.0.0-alpha1 è possibile:

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

oppure puoi impostarlo programmaticamente .

Nota: se si sta eseguendo l'aggiornamento da una versione precedente della libreria di supporto, non dimenticare di aumentare la versione dell'SDK di compilazione. Controlla le versioni della libreria di supporto qui: versioni della libreria di supporto

Tuttavia, è possibile che venga visualizzato il messaggio labelVisibilityMode non trovato durante la compilazione, se l'app dipende dalle versioni precedenti della libreria di supporto alla progettazione. In questo caso, provare ad eseguire l'aggiornamento a una versione della dipendenza data, che dipende almeno dalla versione 28.0.0-alpha1 della libreria di supporto alla progettazione. Se ciò non è possibile, definire esplicitamente la dipendenza.

Se usi Gradle

  1. Puoi controllare le tue depdendecies eseguendo l' attività delle dipendenze e cercando il numero di versione di com.android.support:design .
  2. Per aggiungere esplicitamente la dipendenza del supporto alla progettazione in build.gradle :

    implementazione 'com.android.support:design:28.0.0'


4

Per una risposta aggiornata utilizzando l'impostazione predefinita. Aggiornamento all'ultima libreria di design

implementazione "com.android.support:design:28.0.0"

e aggiungi gli attributi xml BottomNavigationView

app:itemHorizontalTranslationEnabled="false"

puoi metterlo anche come programmaticamente

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

Puoi trovare la fonte qui BottomNavigationView

Spero che questo ti aiuti.


Da cosa differisce questo app:labelVisibilityMode?
mercoledì

@wonsuc riguarda l'animazione dell'icona e del testo che l'elemento selezionato sta animando. Mentre labelVisibilityMode serve per mostrare se si desidera mostrare l'icona con il testo o solo l'icona da visualizzare quando selezionata.
Lester L.

3

Per la tua BottomNavigationViewaggiuntaapp:labelVisibilityMode="unlabeled"

<android.support.design.widget.BottomNavigationView
        app:menu="@menu/bn_menu"
        android:layout_height="56dp"
        android:layout_width="match_parent"
        app:labelVisibilityMode="unlabeled">

</android.support.design.widget.BottomNavigationView>

che risulta in quanto segue

Vista navigazione inferiore Android Disattiva testo e Maiusc


3

È molto semplice, basta aggiungere una proprietà in BottomNaviationView

app:labelVisibilityMode="unlabeled"

2

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

Se stai affrontando questo strano comportamento, ecco la soluzione. Rimuovi

android:fitsSystemWindows="true"

nel layout principale del frammento. Basta rimuovere questo e boom! BottomNavigationView funzionerà bene, ora può essere mostrato con testo e icona. Ho avuto questo nel mio coordinatore principale Layout di frammento.

Inoltre, non dimenticare di aggiungere

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

nella tua attività per disabilitare la modalità di spostamento. Sebbene non sia esattamente correlato alla domanda posta, ma lo trovo ancora utile.


1
@ abbath0767 hai visto link questo? Potrebbe esserti utile.
Kishan Solanki,

Pensavo di aver già provato di tutto, grazie mille, non mi aspettavo di trovare direttamente la risposta che cercavo.
BekaBot,

1
Piacere @BekaBot
Kishan Solanki il

2

Questa è una libreria di terze parti che uso e ha molte opzioni di personalizzazione come la disabilitazione della modalità shift, che mostra solo icone, impostazione della dimensione delle icone, ecc. BottomNavigationViewEx


2

Per rimuovere completamente le animazioni:

Se vuoi anche sbarazzarti di quella fastidiosa piccola animazione del margine superiore, hai bisogno di più codice di riflessione. Ecco la soluzione completa che rimuove qualsiasi animazione:

@SuppressLint("RestrictedApi")
private 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);

            Field shiftAmount = item.getClass().getDeclaredField("mShiftAmount");
            shiftAmount.setAccessible(true);
            shiftAmount.setInt(item, 0);
            shiftAmount.setAccessible(false);

            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {
        Timber.e(e, "Unable to get fields");
    } catch (IllegalAccessException e) {
        Timber.e(e, "Unable to change values");
    }
}

E assicurati di aggiungerlo al tuo file di configurazione proguard:

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView { 
    int mShiftAmount;
}

Android 9 (livello API 28) introduce nuove restrizioni sull'uso di interfacce non SDK e questo non funzionerebbe se il targeting 28. developer.android.com/about/versions/pie/…
ernestkamara

2

aggiorna la tua libreria di supporto alla 28.0.0.

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

1

Se stai usando il supporto: design: 28.0.0 aggiungi questa app per la linea: labelVisibilityMode = "senza etichetta" a BottomNavigationView


0

voglio solo aggiungere che sopra questo metodo disableShiftMode aggiungi anche il codice sottostante. @SuppressLint ( "RestrictedApi")


0

https://android.jlelse.eu/disable-shift-label-animation-from-bottom-navigation-android-b42a25dcbffc

1

<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:itemHorizontalTranslationEnabled="false"/>

2

<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:labelVisibilityMode="labeled"/>

3

<resources xmlns:tools="http://schemas.android.com/tools">
<dimen name="design_bottom_navigation_active_text_size"
    tools:override="true">12sp</dimen>


-1

Puoi usarlo per mostrare sia il testo che le icone su BottomNevigationView da 3 a 5 elementi e interrompere lo spostamento.

 app:labelVisibilityMode="labeled"

Ma dovrai affrontare un problema di taglio lungo del testo su BottmNevigationView per 5 articoli. per questo, ho trovato una buona soluzione per smettere di spostare il testo e le icone di BottomNevigationView. Puoi anche interrompere lo spostamento del testo e anche le icone su BottomNevigationView. Le istantanee del codice sono fornite qui.

1. Aggiungi questa riga di codice in BottomNevigationView come mostrato

<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. Aggiungi voci di menu come segue: -

 <?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. Aggiungi questo stile nel file 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) Aggiungili nella cartella 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>

Ho ricevuto aiuto da questi link e link . Puoi anche ottenere aiuto studiando questi link . Questo mi aiuta molto. Spero che anche questo ti aiuti. Grazie....

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.