Jak wyłączyć tryb zmiany BottomNavigationView?

146

BottomNavigationView nie pokazuje tytułów menu, które są nieaktywne.

Jak wyświetlić tytuły wszystkich elementów menu w bottomNavigationBar? Problem w tym, że w moim przypadku pokazywany jest tylko tytuł klikniętego elementu.

wprowadź opis obrazu tutaj

Natan Rubinstein
źródło
1
Możliwy duplikat nowego dolnego paska nawigacyjnego Androida
Radhey
Oto przydatna odpowiedź, jeśli chcesz całkowicie usunąć dowolną animację: stackoverflow.com/a/51052247/2352699
Fred Porciúncula

Odpowiedzi:

330

Realizacja BottomNavigationViewwarunku has: gdy jest więcej niż 3 elementy, użyj trybu przesunięcia.

W tej chwili nie możesz go zmienić za pomocą istniejącego interfejsu API, a jedynym sposobem na wyłączenie trybu zmiany jest użycie odbicia.

Będziesz potrzebować klasy pomocnika:

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

Następnie zastosuj disableShiftModemetodę na swoim BottomNavigationView, ale pamiętaj, że jeśli nadmuchujesz widok menu z kodu, musisz go wykonać po zawyżeniu.

Przykładowe użycie:

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

PS.

Pamiętaj, że będziesz musiał wykonywać tę metodę za każdym razem, gdy zmieniasz pozycje menu w pliku BottomNavigationView.

AKTUALIZACJA

Musisz także zaktualizować plik konfiguracyjny proguard (np. Proguard-rules.pro), powyższy kod używa odbicia i nie zadziała, jeśli program proguard zaciemni mShiftingModepole.

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

Dziękuję Muhammadowi Alfaifi za wskazanie tego problemu i udostępnienie fragmentu .

AKTUALIZACJA 2

Jak zwróciła uwagę Jolanda Verhoef, nowa biblioteka Support ( 28.0.0-alpha1), a także nowa biblioteka Material Components ( 1.0.0-beta01) oferuje publiczną właściwość, która może być używana do manipulowania trybem przesuwania w 3 pozycjach menu.

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

W bibliotece Komponenty materiałów ma to również zastosowanie, jeśli istnieje 5 pozycji menu.

AKTUALIZACJA 3

Jak zauważył @ThomasSunderland, możesz ustawić tę właściwość na false app:itemHorizontalTranslation="false"bez Enabledpostfiksa, aby wyłączyć animację przesunięcia.

możesz zapoznać się z pełnym przewodnikiem dotyczącym stylizacji Nawigacji Dolnej tutaj

Przemysław Piechota. kibao
źródło
10
**** Proguard :(
Muhammad Alfaifi
17
Pole będzie zaciemnione, więc nie ma możliwości zmiany jego wartości, chyba że wykluczysz je w swoim pliku reguł
proguard
8
-keepclassmembers klasa android.support.design.internal.BottomNavigationMenuView {boolean mShiftingMode; }
Muhammad Alfaifi,
8
Czasami naprawdę się zastanawiam, dlaczego Google wymusza implementacje wyświetlania na programistach. Chociaż w samej aplikacji Google+ są 4 opcje, ta prosta funkcja powinna być dostępna za pośrednictwem prostej funkcji, jeśli była dostępna! Podobny problem występował z TabLayout, który został naprawiony znacznie później w bibliotece wsparcia. Dziękuję za obejście problemu dla Original Replier i @MuhammadAlfaifi za ulepszenie tego.
sud007
19
Nowa biblioteka obsługi (28.0.0-alpha1) obsługuje zmianę tego zachowania za pomocą aplikacji: labelVisibilityMode = "labeled"
Jolanda Verhoef
50

Od obsługi biblioteki 28.0.0-alpha1:

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
Junbin Deng
źródło
1
Używam tej wersji biblioteki obsługi, ale nadal pojawia się błąd „labelVisibilityMode” nie został znaleziony.
Sagar Maiyad,
1
Działa prawidłowo. Nie musisz się zastanawiać.
Wielkie
1
@Riser upewnić używasz app:nieandroid:
Carson Holzheimer
28

Aby wyłączyć animację tekstu, możesz również użyć tego w swoim pliku dimens.xml:

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

Może być konieczne dodanie tego w swoim manifeście:

tools:override="true"
Pafoid
źródło
nie działa. Wydaje mi się, że musiałem po prostu dodać to w /values/dimens.xml?
Rohan Kandwal,
10
@RohanKandwal trzeba dodaćtools:override="true"
Boy
@Boy Thanks, spróbuje.
Rohan Kandwal
zmienić tylko rozmiar tekstu.
The Dude,
Muszę tylko umieścić to w moim pliku dimens.xml:<dimen name="design_bottom_navigation_active_text_size" tools:ignore="PrivateResource">12sp</dimen>
Fernando Barbosa
22

Możesz teraz używać app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"w28-alpha

  • labeled sprawi, że wszystkie etykiety będą widoczne.
  • unlabeled pokaże tylko ikony.
  • selected pokaże tylko etykietę dla wybranego elementu i przesunie elementy.
  • autowybierze oznaczone lub wybrane na podstawie liczby posiadanych elementów. oznaczone dla 1-3 elementów i wybrane dla 3+ elementów.
Aidan Laing
źródło
1
dzięki Lunkie! To dla mnie najlepsze i najłatwiejsze rozwiązanie
Gregriggins36
Gdzie dodać ten wiersz kodu. Próbowałem dodać, ale nie znaleziono błędu.
Abdulwahid,
@Abdulwahid, możesz dodać to w xml dolnego paska nawigacyjnego, gdy masz bibliotekę wsparcia 28 lub nowszą
Aidan Laing
@Lunkie dzięki, teraz jest jasne, gdy obsługuje bibliotekę 28
Abdulwahid
17

Odpowiedź Przemysława w Kotlinie jako funkcja rozszerzenia

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

Użycie (z rozszerzeniami Kotlin dla systemu Android):

bottom_navigation_view.disableShiftMode()
ElegyD
źródło
Praca dla Kotlin. dlaczego potrzebujemy tej adnotacji @SuppressLint ("RestrictedApi") czy możesz wyjaśnić, proszę?
Ranjith Kumar
11

Pracuje dla mnie

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

lub

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
UgAr0FF
źródło
mój działał dobrze, aż target = 27, ale od target = 28, jest uszkodzony, tekst nie jest już wyświetlany. Ale setLabelVisibilityMode załatwia sprawę, teraz działa jak urok
joke4me
10

Aby wyłączyć animację tekstu i zmniejszyć rozmiar czcionki, użyj tego w pliku dimens.xml:

<dimen name="design_bottom_navigation_text_size">10sp</dimen> 
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
Abhishek
źródło
Można Navigate-> File...> design_bottom_navigation_item.xml, aby zobaczyć, że nie ma innego sposobu.
arekolek
6

AKTUALIZACJA

w Android SDK w wersji 28 i nowszych zostały one zmienione item.setShiftingMode(false)naitem.setShifting(false)

Usunęli też pole mShiftingMode

Więc użycie będzie

 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());
        }
    }
}
Narek Hayrapetyan
źródło
możesz użyć tego kodu poniżej. @SuppressLint ( "RestrictedApi") removeShiftMode zabawy (zobacz: BottomNavigationView) {Val menuView = view.getChildAt (0), a BottomNavigationMenuView menuView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED menuView.buildMenuView ()}
głębokie P
5

Jak zauważyli inni, od czasu obsługi biblioteki 28.0.0-alpha1 możliwe jest:

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

lub możesz ustawić to programowo .

Uwaga: jeśli aktualizujesz ze starszej wersji biblioteki wsparcia, nie zapomnij o podniesieniu kompilacji wersji SDK. Sprawdź wersje biblioteki pomocy technicznej tutaj: Obsługuj wersje biblioteki

Jednak nadal możesz otrzymać komunikat nie znaleziono labelVisibilityMode podczas kompilacji, jeśli Twoja aplikacja zależy od starszych wersji biblioteki obsługi projektowania. W takim przypadku spróbuj zaktualizować do wersji podanej zależności, która zależy przynajmniej od wersji 28.0.0-alpha1 biblioteki obsługi projektowania. Jeśli nie jest to możliwe, jawnie zdefiniuj zależność.

Jeśli używasz Gradle

  1. Możesz sprawdzić swoje zależne gatunki, uruchamiając zadanie zależności i wyszukując numer wersji com.android.support:design .
  2. Aby jawnie dodać zależność obsługi projektu w pliku build.gradle :

    wdrożenie „com.android.support:design:28.0.0”

Richárd Bogdán
źródło
4

Aby uzyskać zaktualizowaną odpowiedź, użyj domyślnej. Zaktualizuj do najnowszej biblioteki projektów

implementacja „com.android.support:design:28.0.0”

i umieść w swoich atrybutach BottomNavigationView xml

app:itemHorizontalTranslationEnabled="false"

możesz to również umieścić programowo

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

Możesz znaleźć źródło tutaj BottomNavigationView

Mam nadzieję, że to ci pomoże.

Lester L.
źródło
Czym to się różni app:labelVisibilityMode?
wygrał
@wonsuc chodzi o animację ikony i tekstu, który animuje wybrany element. Podczas gdy labelVisibilityMode służy do wyświetlania, czy chcesz wyświetlać ikonę z tekstem, czy tylko ikonę, która ma być wyświetlana po wybraniu.
Lester L.
3

Do twojego BottomNavigationViewdodatkuapp: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>

co skutkuje następującym

Dolny widok nawigacji Androida Wyłącz tekst i przesunięcie

Wszystko jest Vаиітy
źródło
3

To bardzo proste, wystarczy dodać właściwość w BottomNaviationView

app:labelVisibilityMode="unlabeled"
Nevil Ghelani
źródło
2

Miałem dziwne zachowanie z BottomNavigationView. Kiedy wybierałem dowolny element / fragment w nim, fragment wypycha BottomNavigationView nieco niżej, więc tekst BottomNavigationView przechodzi poniżej ekranu, więc widoczne są tylko ikony, a tekst jest ukrywany po kliknięciu dowolnego elementu.

Jeśli masz do czynienia z tym dziwnym zachowaniem, oto rozwiązanie. Po prostu usuń

android:fitsSystemWindows="true"

w głównym układzie fragmentu. Po prostu usuń to i bum! BottomNavigationView będzie działać dobrze, teraz można go wyświetlić z tekstem i ikoną. Miałem to w moim głównym Koordynatorze Układ fragmentu.

Nie zapomnij też dodać

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

w swojej aktywności, aby wyłączyć tryb zmiany biegów. Chociaż nie jest to dokładnie związane z zadanym pytaniem, nadal uważam to za pomocne.

Kishan Solanki
źródło
1
@ abbath0767 widziałeś link do tego? Może ci pomóc.
Kishan Solanki
Myślałem, że już wszystkiego wypróbowałem, bardzo dziękuję, nie spodziewałem się bezpośrednio znaleźć odpowiedzi, której szukałem.
BekaBot
1
Pleasure @BekaBot
Kishan Solanki
2

To jest biblioteka innej firmy, której używam i ma wiele opcji dostosowywania, takich jak wyłączenie trybu zmiany, wyświetlanie tylko ikon, ustawianie rozmiaru ikon itp. BottomNavigationViewEx

Pei
źródło
2

Aby całkowicie usunąć animacje:

Jeśli chcesz pozbyć się tej irytującej animacji górnego marginesu, potrzebujesz więcej kodu odbicia. Oto kompletne rozwiązanie, które usuwa wszelkie animacje:

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

I pamiętaj, aby dodać to do pliku konfiguracyjnego programu Proguard:

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView { 
    int mShiftAmount;
}
Fred Porciúncula
źródło
Android 9 (poziom API 28) wprowadza nowe ograniczenia w korzystaniu z interfejsów innych niż SDK i to nie zadziała, jeśli 28. developer.android.com/about/versions/pie/ ...
ernestkamara
2

zaktualizuj bibliotekę pomocy technicznej do wersji 28.0.0.

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
M Moersalin
źródło
1

Jeśli używasz support: design: 28.0.0 dodaj tę aplikację liniową: labelVisibilityMode = "unlabeled" do swojego BottomNavigationView

Omar Hassan
źródło
0

po prostu chcę dodać, że powyżej tej metody disableShiftMode dodaj też poniższy kod. @SuppressLint ("RestrictedApi")

Aleesha Kanwal
źródło
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>

kreker
źródło
-1

Możesz użyć tego do wyświetlania zarówno tekstu, jak i ikon w BottomNevigationView dla 3 do 5 elementów i zatrzymania przesuwania.

 app:labelVisibilityMode="labeled"

Ale napotkasz problem z wycinaniem długiego tekstu w BottmNevigationView dla 5 elementów. w tym celu znalazłem dobre rozwiązania, aby zatrzymać przesuwanie tekstu, a także ikony BottomNevigationView. Możesz także zatrzymać przesuwanie tekstu, a także ikon w widoku BottomNevigationView. Tutaj zamieszczono fragmenty kodu.

1. Dodaj tę linię kodu w BottomNevigationView, jak pokazano

<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. Dodaj elementy menu w następujący sposób: -

 <?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. Dodaj ten styl w pliku 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) Dodaj je w folderze 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>

Mam pomocy od tych linku i odwołuje Ty możesz również uzyskać uzyskać pomoc studiując te links.This pomaga mnie lot.Hope to również pomóc. Dzięki....

Rahul Kushwaha
źródło