Как отключить режим сдвига BottomNavigationView?


BottomNavigationView не показывает заголовок меню, которые неактивны.

Как показать названия всех элементов меню в bottomNavigationBar? Проблема в том, что в моем случае показан только заголовок элемента, который нажат.

13 108

13 ответов:

реализация BottomNavigationView имеет условие: когда больше чем 3 деталя после этого используют режим переноса.

на данный момент Вы не можете изменить его через существующий API, и единственный способ отключить режим сдвига-использовать отражение.

вам понадобится вспомогательный класс:

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

а затем применить disableShiftMode метод BottomNavigationView, но помните, если вы надуваете вид меню из вашего кода, Вы должны выполнить его после надувания.

пример использование:

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

PS.

помните, что вам нужно будет выполнять этот метод каждый раз, когда вы меняете пункты меню в вашем BottomNavigationView.

обновление

вам также необходимо обновить файл конфигурации proguard (например proguard-rules.pro), код выше использует отражение и не будет работать, если proguard запутать

Так как библиотека поддержки 28.0.0-alpha1:

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

чтобы отключить текстовую анимацию, вы также можете использовать ее в своих измерениях.xml-файл:

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

ответ Пшемыслава в Котлине как функция расширения

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

использование (с расширениями Kotlin Android):

bottom_navigation_view.disableShiftMode()

теперь вы можете использовать приложение: labelVisibilityMode="[помечено, не помечено, выбрано, авто] " в 28-alpha

labeled сохранит все метки видимыми.

без метки будут отображаться только значки.

выбранный будет отображаться только метка для выбранного элемента и элементов сдвига.

авто будет выбирать помеченные или выбранные на основе количества элементов, которые у вас есть. с надписью на 1-3 пунктов и 3 пунктов.

чтобы отключить анимацию текста и уменьшить размер шрифта, используйте это в ваших dimens.xml-файл:

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

для меня

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

у меня было какое-то странное поведение с BottomNavigationView. Когда я выбирал какой-либо элемент/фрагмент в нем, фрагмент толкает BottomNavigationView немного ниже, поэтому текст BottomNavigationView идет ниже экрана, поэтому видны только значки, а текст скрывается при нажатии любого элемента.

Если вы столкнулись с этим странным поведением, то здесь решение. Просто удалите

android:fitsSystemWindows="true"

в корневом макете фрагмента. Просто снимите это и бум! BottomNavigationView будет работать нормально, теперь он может быть показан с текстом и значком. У меня это было в моем корневом координаторе фрагмента.

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

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

в вашей деятельности, чтобы отключить режим сдвига. Хотя это не совсем связано с заданным вопросом, но все же я нахожу это полезным.

это сторонняя библиотека, которую я использую, и у нее есть много вариантов настройки, таких как отключение режима сдвига, отображение только значков, установка размера значков и т. д. BottomNavigationViewEx

как указывали другие, так как библиотека поддержки 28.0.0-alpha1 можно:

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

или вы можете настроить его программно.

Примечание: Если вы обновляете более старую версию библиотеки поддержки, не забудьте поднять версию compile SDK. Проверьте версии поддержки libraray здесь: поддержка версий библиотеки

однако, вы все равно можете получить labelVisibilityMode нет нашел сообщение при компиляции, если ваше приложение зависит от более старых версий библиотеки поддержки проектирования. Если это так, попробуйте обновить до версии данной зависимости, которая зависит по крайней мере от версии 28.0.0-alpha1 библиотеки поддержки проектирования. Если это невозможно, определите зависимость явно.

Если вы используете Gradle

  1. вы можете проверить ваши depdendecies мимо работает зависимости задача и поиск номер версии com.андроид.поддержка:дизайн.
  2. чтобы добавить зависимость поддержки дизайна явно в вашем построить.gradle:

    реализация ' com.андроид.поддержка:дизайн:28.0.0'

для обновленного ответа используется значение по умолчанию. Обновление до последней библиотеке

реализация " com.андроид.поддержка:дизайн:28.0.0"

и положить в BottomNavigationView XML атрибуты

app:itemHorizontalTranslationEnabled="false"

вы можете поставить его также как программно

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

Вы можете найти источник здесь BottomNavigationView

надеюсь, что это поможет вам.

чтобы полностью удалить анимацию:

если вы также хотите избавиться от этой раздражающей маленькой анимации верхнего поля, вам нужно больше кода отражения. Вот полное решение, которое удаляет любую анимацию:

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

и обязательно добавьте это в свой файл конфигурации proguard:

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

просто хочу добавить, что выше этот метод disableShiftMode добавить ниже код тоже. @SuppressLint ("RestrictedApi")