BottomNavigationView wyświetla przez cały czas zarówno ikony, jak i etykiety tekstowe


125

Używam android.support.design.widget.BottomNavigationView z biblioteki obsługi projektów w wersji 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"/>

Kiedy w @ menu / bottom_navigation_main są tylko trzy akcje, przez cały czas wyświetla zarówno ikony, jak i etykiety tekstowe.

Jaki jest sposób wyświetlania zarówno ikon, jak i etykiet tekstowych przez cały czas, gdy są więcej niż trzy akcje.


W menu bottom_navigation_main.xml, jeśli masz androida: showAsAction = "ifRoom", zmień go na android: showAsAction = "zawsze" dla każdego elementu.
Shashank Udupa

Nie, to nie zadziałało. próbowałem tego wcześniej.
Android Developer

Czy możesz pokazać swój plik xml 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> '
programista Androida

4
place app: labelVisibilityMode = "oznaczone" w BottomNavigationView.
Shrawan

Odpowiedzi:


327

Dla każdego, kto wciąż szuka rozwiązania i nie chce polegać na bibliotekach innych firm lub odbiciu czasu wykonywania, BottomNavigationView w Support Library 28 / Jetpack natywnie obsługuje zawsze posiadanie etykiety tekstowej.

To jest metoda, której szukasz.

Lub w formacie XML, app:labelVisibilityMode="labeled"


jakiej wersji biblioteki potrzebuję?
DaniloDeQueiroz

wsparcie biblioteki 28-
alpha1

Możesz także zmienić tryb widoczności na „automatyczny”, aby wyświetlać tekst ikony tylko po naciśnięciu / zaznaczeniu. Kod: app: labelVisibilityMode = "auto"
Kenny Dabiri

Jesteś meżczyzną! Dziękuję, że działa z najnowszą wersją biblioteki materiałów.
sud007

68

AKTUALIZACJA OD 8 maja 2018

Możesz używać app:labelVisibilityMode="labeled" bezpośrednio w<android.support.design.widget.BottomNavigationView />

Źródło: https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode

Nie potrzebuję tego poniżej przydługiego rozwiązania.

POPRZEDNIA ODPOWIEDŹ

Miałem dziwne zachowanie z BottomNavigationView. Kiedy wybierałem dowolny element / fragment w nim, fragment wypycha BottomNavigationView nieco niżej, więc tekst BottomNavigationView trafia 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 to usuń 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.removeShiftMode(bottomNavigationView);

w swojej aktywności, aby wyłączyć tryb zmiany biegów.

Oto ta klasa:

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

To w połączeniu z odpowiedzią STAR_ZERO rozwiązało mój problem!
Christopher Smit,

Podczas rozmowy disableShiftModei na zajęciach removeShiftMode. Oprócz tej małej rozbieżności, Twoja odpowiedź rozwiązała problem za mnie. Mam teraz pięć elementów menu bez przesuwania i z tekstem + ikoną. Dziękuję bardzo dużo!
Yamakuzure

Idealny. Gdy masz więcej niż 3 elementy w dolnej nawigacji niż, pojawia się tryb przesuwania. Używając tego, możesz wyłączyć to przesuwanie, a tym samym wszystkie ikony z tekstem pojawią się jednocześnie.
Kishor Bikram Oli

1
Jest to nieograniczony interfejs API i nie działa w wersji 28 biblioteki obsługi. +. Zaakceptowana odpowiedź @shaishgandhi jest bardziej odpowiednim sposobem na zrobienie tego.
okarakose

19

W wersji 25 jest to trudne.

Wypróbuj ten kod. Ale myślę, że to nie jest dobre rozwiązanie.

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

W Android Studio należy dodać następujący kod: `` // noinspection RestrictedApi itemView.setShiftingMode (false); // noinspection RestrictedApi itemView.setChecked (false); ``
Jiezhi.G

4
nadal przesuwa elementy
CodeToLife

1
Idealny !! wyświetla zarówno ikonę, jak i tekst. Ale tryb zmiany biegów (fałsz) nie działa.
Minkoo

To w połączeniu z odpowiedzią KishanSolanki124 rozwiązało mój problem!
Christopher Smit,

11

Oto funkcja rozszerzenia Kotlin, która łączy rozwiązanie @STAR_ZERO i @ 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)
        }
    }
}

Aby z niego skorzystać:

myBottomNavigation.disableShiftMode()

10

Chcesz taki efekt?

Kliknij tutaj, aby wyświetlić obraz

Jeśli tak, polecam wypróbowanie BottomNavigationViewEx


1
Twoja biblioteka jest dobra i imponująca.Ale chciałem osiągnąć tę funkcjonalność przy użyciu biblioteki projektów 25.0.0. Niestety jest to sprzeczne z praktyką projektowania
Androida

Nie jest to sprzeczne ze specyfikacją Material Design, zgodnie z „Stałym dolnym paskiem nawigacji” w dokumentacji . Dziękuję również za udostępnienie tej niesamowitej biblioteki.
Serg de Adelantado

1
Jest to sprzeczne ze specyfikacjami Material Design. Jeśli przeczytasz dokument, który dostarczyłeś, zobaczysz, że jest w nim wyraźnie napisane „Jeśli jest cztery lub pięć działań, wyświetlaj nieaktywne widoki tylko jako ikony”.
Felipe

8

Możesz użyć tego do wyświetlania zarówno tekstu, jak i ikon w BottomNevigationView

app:labelVisibilityMode="labeled"

Jeśli tego używasz, będziesz mógł zobaczyć zarówno ikonę, jak i tekst

<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

Możesz użyć app: labelVisibilityMode = "labeled" bezpośrednio w

<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

w klasie BottomNavigationView znajduje się pole BottomNavigationMenuView, a w BottomNavigationMenuView pole BottomNavigationItemView [], czyli elementy na dolnym pasku.

Powiedz n to liczba elementów, BottomNavigationMenuView wywoła BottomNavigationItemView.setShiftingMode (n> 3) dla każdego elementu członkowskiego tablicy BottomNavigationItemView []. Ta funkcja decyduje o zachowaniu (pokaż tytuł zawsze lub tylko po zaznaczeniu).

więc sposobem na zawsze pokazanie tytułów jest wywołanie tej metody i możesz użyć refleksji, aby uzyskać dostęp do pól prywatnych.

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

To jest bardzo dobre, po prostu musimy się upewnić, że BottomNavigationMenuView również się nie przesuwa. -> f = menuView.getClass (). getDeclaredField ("mShiftingMode"); f.setAccessible (true); f.setBoolean (menuView, false);
Stephane K.

4

Aby pokazać tytuły przez całą drogę. Wypróbuj ten kod 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)
    }
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.