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

Когда в @ menu / bottom_navigation_main есть только три действия, он всегда отображает и значки, и текстовые метки.

Каким образом можно отображать одновременно и значки, и текстовые метки при наличии более трех действий.

Разработчик Android
источник
В меню bottom_navigation_main.xml, если у вас есть android: showAsAction = "ifRoom", измените его на android: showAsAction = "always" для каждого элемента.
Шашанк Удупа
Нет, не сработало. я пробовал это раньше.
Android Developer
Можете ли вы показать свой xml файл меню
Шашанк Удупа
'<? 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> '
разработчик Android
4
поместите app: labelVisibilityMode = "label" в BottomNavigationView.
Shrawan

Ответы:

327

Для тех, кто все еще ищет решение и не хочет полагаться на сторонние библиотеки или отражение во время выполнения, BottomNavigationView в библиотеке поддержки 28 / Jetpack изначально поддерживает всегда наличие текстовой метки.

Это тот метод, который вам нужен.

Или в XML, app:labelVisibilityMode="labeled"

shaishgandhi
источник
какая версия библиотеки мне нужна?
DaniloDeQueiroz
библиотека поддержки 28-alpha1 +
shaishgandhi
Вы также можете изменить режим видимости на «автоматический», чтобы отображать текст значка только при нажатии / фокусировке. Код: app: labelVisibilityMode = "auto"
Кенни
Ты человек! Спасибо, что работает с последней версией библиотеки материалов.
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 будет работать нормально, теперь он может отображаться с текстом и значком. У меня это было в моем корневом CoordinatorLayout фрагмента.

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

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. Помимо этого небольшого несоответствия, ваш ответ решил проблему для меня. Теперь у меня есть пять пунктов меню без сдвига и с текстом + значок. Спасибо очень много!
Yamakuzure
Отлично. Когда у вас более 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);
}
STAR_ZERO
источник
В Android Studio следует добавить такой код: `` // noinspection RestrictedApi itemView.setShiftingMode (false); // без проверки RestrictedApi itemView.setChecked (false); ''
Jiezhi.G
4
он по-прежнему перекладывает предметы
CodeToLife
1
Отлично !! отображает и значок, и текст. Но режим переключения (false) не работает.
Минку
Это в сочетании с ответом 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()
chetbox
источник
10

Вы хотите этого эффекта?

Щелкните здесь, чтобы просмотреть изображение

Если да, то я рекомендовал вам попробовать BottomNavigationViewEx .

ittianyu
источник
1
Ваша библиотека - хорошая и впечатляющая работа. Но я стремился достичь этой функциональности с помощью библиотеки дизайна 25.0.0. К сожалению, это противоречит практике
разработки Android
Это не противоречит спецификациям Material Design, согласно «Фиксированной нижней панели навигации» в документации . Также я лично благодарен за то, что поделились этой замечательной библиотекой.
Серж де
1
Это ПРОТИВ спецификаций Material Design. Если вы прочтете предоставленный вами документ, вы увидите, что в нем явно сказано: «Если есть четыре или пять действий, отображать неактивные представления только в виде значков».
Felipe
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

Вы можете использовать app: labelVisibilityMode = "labeled" непосредственно в

<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, ложь);
Стефан К.
4

Чтобы заголовки отображались полностью. Попробуйте этот код 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)
    }
}
Гарри Чжан
источник