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


146

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

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

введите описание изображения здесь



Вот полезный ответ, если вы хотите полностью удалить любую анимацию: stackoverflow.com/a/51052247/2352699
Фред Porciúncula

Ответы:


330

Реализация 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 запутывает mShiftingModeполе.

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

Спасибо Мухаммеду Альфаифи за указание на эту проблему и предоставление фрагмента .

ОБНОВЛЕНИЕ 2

Как отметила Jolanda Verhoef, новая библиотека поддержки ( 28.0.0-alpha1), а также новая библиотека компонентов материалов (1.0.0-beta01 ) предлагает открытое свойство, которое можно использовать для управления режимом смещения над 3 пунктами меню.

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

В библиотеке компонентов материалов это также применимо, если есть 5 пунктов меню.

ОБНОВЛЕНИЕ 3

Как также отметил @ThomasSunderland, вы можете установить для этого свойства значение false app:itemHorizontalTranslation="false"безEnabled постфикса, чтобы отключить смещение анимации.

Вы можете проверить полное руководство по стилю BottomNavigation здесь


10

17
Поле будет запутано, поэтому невозможно изменить его значение, если вы не исключите его из файла правил
proguard

8
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {boolean mShiftingMode; }
Мухаммед Альфаифи,

8
Иногда мне действительно интересно, почему Google заставляет разработчиков реализовывать свои представления. Хотя в самом приложении Google+ есть 4 опции, эта простая функция должна была быть доступна через простую функцию, если она доступна! Подобная проблема была с TabLayout, которая была исправлена ​​намного позже в библиотеке поддержки. Спасибо за этот обходной путь для Original Replier и @MuhammadAlfaifi за улучшение этого.
sud007

19
Новая библиотека поддержки (28.0.0-alpha1) поддерживает изменение этого поведения с помощью приложения: labelVisibilityMode = "labeleled"
Jolanda Verhoef

50

Начиная с библиотеки поддержки 28.0.0-alpha1:

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

1
Я использую эту версию библиотеки поддержки, но по-прежнему получаю сообщение об ошибке "labelVisibilityMode" не найдено.
Сагар Майяд

1
Работает должным образом. Не нужно идти на размышления. Спасибо за тонну
Бхупеш

1
@Riser убедитесь , что вы используете app:неandroid:
Carson Holzheimer

28

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

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

Вам также может понадобиться добавить это в свой манифест:

tools:override="true"

не работает. Я считаю, что мне нужно было просто добавить это в /values/dimens.xml?
Рохан Кандвал

10
@RohanKandwal нужно добавитьtools:override="true"
Бой

@Boy Спасибо, попробую.
Рохан Кандвал

только изменить размер текста.
Чувак

Мне просто нужно поместить вот это в свой файл измерения.xml:<dimen name="design_bottom_navigation_active_text_size" tools:ignore="PrivateResource">12sp</dimen>
Фернандо Барбоза

22

Теперь вы можете использовать app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"в28-alpha

  • labeled будет держать все метки видимыми
  • unlabeled будут показывать только иконки.
  • selected будет отображаться только метка для выбранного элемента и сдвиг элементов.
  • autoвыберет маркированные или выбранные в зависимости от количества предметов, которые у вас есть. помечены для 1-3 предметов и выбраны для 3+ предметов.

1
спасибо Ланки! Это лучшее и самое простое решение для меня
Gregriggins36

Куда добавить эту строку кода. Я пытался добавить, но ошибка не найдена.
Абдулвахид

@Abdulwahid вы можете добавить это в xml нижней панели навигации, если у вас есть библиотека поддержки 28 или выше
Aidan Laing

@Lunkie спасибо, теперь ясно, что однажды поддержу библиотеку 28
Абдулвахид

17

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

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

Работаю на котлин. почему мы должны использовать эту аннотацию @SuppressLint ("RestrictedApi"), вы можете объяснить, пожалуйста?
Ранджит Кумар

11

Работает для меня

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

или

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

у меня все работало нормально, пока цель = 27, но из цели = 28, она не работает, текст больше не отображается. Но setLabelVisibilityMode делает свое дело для меня, теперь работает как очарование
joke4me

10

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

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

Можно Navigate-> File...> , design_bottom_navigation_item.xmlчтобы увидеть , что нет никакого другого пути.
ареколек

6

ОБНОВИТЬ

в Android SDK версии 28 и выше они изменились item.setShiftingMode(false)наitem.setShifting(false)

Также они убрали поле mShiftingMode

Так что использование будет

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

Вы можете использовать этот код ниже. @SuppressLint ( "RestrictedApi") весело removeShiftMode (вид: BottomNavigationView) {вал menuView = view.getChildAt (0) , как BottomNavigationMenuView menuView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED menuView.buildMenuView ()}
Deep P

5

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

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

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

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

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

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

  1. Вы можете проверить свои зависимости, запустив задачу зависимостей и найти номер версии com.android.support:design .
  2. Чтобы явно добавить поддержку поддержки дизайна в ваш build.gradle :

    реализация 'com.android.support:design:28.0.0'


4

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

реализация "com.android.support:design:28.0.0"

и поместите в ваши атрибуты BottomNavigationView xml

app:itemHorizontalTranslationEnabled="false"

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

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

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

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


Чем это отличается от app:labelVisibilityMode?
wonsuc

@wonsuc - это анимация иконки и текста, которые анимирует выбранный элемент. В то время как labelVisibilityMode для отображения, хотите ли вы показать значок с текстом, или просто значок, который будет отображаться при выборе.
Лестер Л.

3

К вашему BottomNavigationViewдобавлениюapp: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>

что приводит к следующему

Нижняя навигация по Android View Отключить текст и сдвиг



2

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

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

android:fitsSystemWindows="true"

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

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

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

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


1
@ abbath0767 ты видел ссылку на это? Может быть полезно для вас.
Кишан Соланки

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

1
Удовольствие @BekaBot
Кишан Соланки

2

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


2

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

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

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

Android 9 (API уровень 28) вводит новые ограничения на использование не SDK интерфейсов , и это не будет работать , если таргетинг 28. developer.android.com/about/versions/pie/...
ernestkamara

2

обновите вашу библиотеку поддержки до 28.0.0.

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

1

Если вы используете support: design: 28.0.0 добавьте эту строку app: labelVisibilityMode = "unlabeled" в ваш BottomNavigationView


0

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


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>


-1

Вы можете использовать это для отображения текста и значков в BottomNevigationView от 3 до 5 элементов и остановки сдвига.

 app:labelVisibilityMode="labeled"

Но вы столкнетесь с проблемой обрезки длинного текста в BottmNevigationView для 5 элементов. для этого я нашел хорошее решение для остановки смещения текста, а также иконки BottomNevigationView. Вы также можете остановить смещение текста и значков в BottomNevigationView. Снимки кода приведены здесь.

1. Добавьте эту строку кода в BottomNevigationView, как показано

<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. Добавьте пункты меню следующим образом:

 <?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. Добавьте этот стиль в файл 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) Добавьте их в папку 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>

Я получил помощь по этой ссылке и ссылке. Вы также можете получить помощь, изучив эти ссылки. Это мне очень помогает. Надеюсь, это также поможет вам. Спасибо....

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.