Как отключить режим сдвига 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 здесь

Пшемыслав Пехота. kibao
источник
10
**** Proguard :(
Мухаммед Альфаифи
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"
Pafoid
источник
не работает. Я считаю, что мне нужно было просто добавить это в /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()
ElegyD
источник
Работаю на котлин. почему мы должны использовать эту аннотацию @SuppressLint ("RestrictedApi"), вы можете объяснить, пожалуйста?
Ранджит Кумар
11

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

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

или

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
UgAr0FF
источник
у меня все работало нормально, пока цель = 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 Отключить текст и сдвиг

Все это Ваити
источник
3

Это очень просто, просто добавьте свойство в BottomNaviationView

app:labelVisibilityMode="unlabeled"
Невил Гелани
источник
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>

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

Рахул Кушваха
источник