BottomNavigationView постійно відображає як значки, так і текстові мітки


125

Я використовую android.support.design.widget.BottomNavigationView з бібліотеки підтримки підтримки версії 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"/>

Якщо у меню @ @ / bottom_navigation_main є лише три дії, він постійно відображає як значки, так і текстові мітки.

Який спосіб відображати як піктограми, так і текстові мітки, коли є більше трьох дій.


У вашому меню bottom_navigation_main.xml, якщо у вас є android: showAsAction = "ifRoom", змініть його на android: showAsAction = "завжди" для кожного елемента.
Шашанк Удупа

Ні, це не спрацювало. я пробував це раніше.
Android Developer

Чи можете ви показати свій XML файл меню
Shashank Udupa

'<? xml version = "1.0" encoding = "utf-8"?> <меню xmlns: android = " schemas.android.com/apk/res/android " xmlns: app = " schemas.android.com/apk/ res-auto "> <предмет android: id =" @ + id / action_favorites "додаток: showAsAction =" завжди "/> <предмет Android: id =" @ + id / action_schedules "додаток: showAsAction =" завжди "/> < item android: id = "@ + id / action_music" додаток: showAsAction = "завжди" /> <item android: id = "@ + id / account" android: enable = "true" app: showAsAction = "завжди" /> </menu> '
Android Developer

4
розмістити додаток: labelVisibilityMode = "позначено" в BottomNavigationView.
Шраван

Відповіді:


327

Для тих, хто все ще шукає рішення та не хоче покладатися на сторонні бібліотеки чи рефлексію виконання, BottomNavigationView в бібліотеці підтримки 28 / Jetpack споконвічно підтримує завжди текстову мітку.

Це метод, який ви шукаєте.

Або в XML, app:labelVisibilityMode="labeled"


яка версія бібліотеки мені потрібна?
DaniloDeQueiroz

підтримка бібліотеки 28-alpha1 +
shaishgandhi

Ви також можете змінити режим видимості на "автоматичний", щоб відображати текст піктограми лише при натисканні / фокусуванні. Код: додаток: labelVisibilityMode = "авто"
Кенні Дабірі

Ти чоловік! Дякую, що це працює з останньою версією Матеріальної бібліотеки.
sud007

68

ОНОВЛЕННЯ З 8 травня 2018 року

Ви можете використовувати app:labelVisibilityMode="labeled" безпосередньо в<android.support.design.widget.BottomNavigationView />

Джерело: https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode

Не потрібно цього нижче тривалого рішення.

ПОПЕРЕДНІЙ ВІДПОВІДЬ

Я мав деяку дивну поведінку з BottomNavigationView. Коли я вибирав будь-який елемент / фрагмент в ньому, фрагмент штовхає BottomNavigationView трохи нижче, тому текст BottomNavigationView йде нижче екрана, тому видно лише піктограми і текст ховається при натисканні будь-якого елемента.

Якщо ви стикаєтеся з такою дивною поведінкою, тоді ось рішення. Просто видаліть

android:fitsSystemWindows="true"

у вашому кореневому макеті фрагмента. Просто зніміть це і бум! BottomNavigationView буде добре працювати, тепер його можна показати текстом та піктограмою. Це було в моєму кореневому координаторі.

Також не забудьте додати

BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

у вашій діяльності, щоб відключити режим переключення.

Ось цей клас:

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

Це в поєднанні з відповіддю STAR_ZERO вирішило моє питання!
Крістофер Сміт

У дзвінку, який ви маєте disableShiftMode, і в класі removeShiftMode. Крім тієї невеликої невідповідності, ваша відповідь вирішила для мене питання. Зараз у мене є п'ять меню без зміщення та з текстом + піктограмою. Дуже дякую !
Ямакузуре

Ідеально. Якщо в нижній навігації у вас більше 3 елементів, ніж з'являється, з'являється режим зсуву. Використовуючи це, ви можете вимкнути це зміщення і, отже, всі піктограми з текстом з’являються одночасно.
Кішор Бікрам Олі

1
Це необмежений api, і він не працює на підтримці бібліотеки версії 28. +. Прийнята відповідь @shaishgandhi - це більш правильний спосіб зробити це.
okarakose

19

Важко у версії 25.

Спробуйте цей код. Але я думаю, що це не гарне рішення.

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

В Android Studio слід додати такий код: `` // noinspection RestrictedApi itemView.setShiftingMode (false); // noinspection RestrictedApi itemView.setChecked (помилково); `` `
Jiezhi.G

4
це ще зміщення предметів
CodeToLife

1
Ідеально !! відображає іконку, і текст. Але режим переключення (помилковий) не працює.
Minkoo

Це в поєднанні з відповіддю KishanSolanki124 вирішило моє питання!
Крістофер Сміт

11

Ось функція розширення Kotlin, яка поєднує рішення @STAR_ZERO та @ 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)
        }
    }
}

Щоб використовувати його:

myBottomNavigation.disableShiftMode()

10

Ви хочете досягти цього ефекту?

Натисніть тут, щоб переглянути зображення

Якщо так, я рекомендую вам спробувати BottomNavigationViewEx


1
Ваша бібліотека працює добре та вражаюче, але я хотів досягти цієї функціональності за допомогою бібліотеки дизайну 25.0.0 На жаль, це проти практики дизайну андроїдів
Android Developer

Це не суперечить специфікаціям Material Design, згідно з "Фіксованою навігаційною панеллю" в документах . Також моя особиста подяка за те, що поділилася цією дивовижною бібліотекою
Серг де Аделантадо

1
Це суперечить специфікаціям Material Design. Якщо ви прочитаєте наданий вами документ, ви побачите, що в ньому прямо написано "Якщо є чотири чи п’ять дій, відображайте неактивні види лише як піктограми".
Феліпе

8

Ви можете використовувати це для відображення тексту та піктограм на BottomNevigationView

app:labelVisibilityMode="labeled"

Якщо ви використовуєте це, ви зможете переглянути як значок, так і текст

<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

Ви можете використовувати додаток: labelVisibilityMode = "позначений" безпосередньо в

<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

у класі BottomNavigationView є поле BottomNavigationMenuView, а в BottomNavigationMenuView - поле BottomNavigationItemView [], яке є елементами в нижній панелі.

Скажімо, n - кількість елементів, BottomNavigationMenuView викличе BottomNavigationItemView.setShiftingMode (n> 3) на кожного члена масиву BottomNavigationItemView []. Ця функція визначає поведінку (показувати назву завжди або лише після вибору).

тому спосіб завжди показувати заголовки - це спробувати викликати цей метод, і ви можете використовувати відображення для доступу до приватних полів.

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

Це дуже добре, просто нам потрібно переконатися, що BottomNavigationMenuView також не зміщується. -> f = menuView.getClass (). getDeclaredField ("mShiftingMode"); f.setAccessible (вірно); f.setBoolean (menuView, false);
стефан к.

4

Показувати заголовки до кінця. Спробуйте цей код Котліна:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.