Як відключити режим BottomNavigationView shift?


146

BottomNavigationView не показує неактивні заголовки меню.

Як відобразити заголовки всіх елементів меню в нижньомуNavigationBar? Проблема полягає в тому, що в моєму випадку відображається лише заголовок елемента, на який натискають.

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


1
Можливий дублікат нової панелі навігації Android
Radhey

Ось корисний відповідь , якщо ви хочете , щоб повністю видалити будь-яку анімацію: stackoverflow.com/a/51052247/2352699
Фред Порсіункул

Відповіді:


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

Як зазначає Йоланда Верхоеф, нова бібліотека підтримки ( 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
Поле буде затуманено, тому жодний спосіб змінити його значення, якщо ви не виключите його у вашому файлі з правилами
прозахисту

8
-keepclassmembers клас android.support.design.internal.BottomNavigationMenuView {boolean mShiftingMode; }
Мухаммед Альфайфі

8
Іноді мені дуже цікаво, чому Google змушує його переглядати реалізацію на розробниках. Хоча в самій програмі Google+ є 4 варіанти, ця проста функція повинна була бути доступною за допомогою простої функції, якщо вона доступна! Аналогічна проблема була з програмою TabLayout, яка була виправлена ​​значно пізніше в бібліотеці підтримки. Дякуємо за вирішення проблеми Original Original Replier та @MuhammadAlfaifi за покращення цього.
sud007

19
Нова бібліотека підтримки (28.0.0-alpha1) підтримує зміну такої поведінки через додаток: labelVisibilityMode = "мічений"
Jolanda Verhoef

50

Оскільки бібліотека підтримки 28.0.0-alpha1:

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

1
Я використовую цю версію бібліотеки підтримки, але все ж помилка в "labelVisibilityMode" не знайдена.
Сагар Майяд

1
Працюючи належним чином. Не потрібно йти на роздуми. Дякую тонну
Бхупеш

1
@Riser переконайтеся, що ви використовуєте app:неandroid:
Карсон

28

Для відключення текстової анімації ви також можете використовувати це у вашому файлі dimens.xml:

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

Вам може знадобитися додати це у свій маніфест:

tools:override="true"

не працює. Я вважаю, що мені довелося просто додати це в /values/dimens.xml?
Рохан Кандвал

10
@RohanKandwal потрібно додатиtools:override="true"
Хлопчик

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

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

Мені просто потрібно помістити так у мій файл dimens.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
Abdulwahid

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

Використання (за допомогою розширень Android від Kotlin):

bottom_navigation_view.disableShiftMode()

Працює на котлін. чому нам потрібно використовувати цю примітку @SuppressLint ("RestrictedApi"), чи можете ви пояснити pls?
Ранджіт Кумар

11

Працює для мене

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

або

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

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

10

Щоб вимкнути анімацію тексту та зменшити розмір шрифту, використовуйте це у вашому файлі dimens.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щоб побачити , що немає ніякого іншого шляху.
arekolek

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"

і покладіть до атрибутів xml BottomNavigationView

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 знизу Відключення тексту та зсув



2

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

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

android:fitsSystemWindows="true"

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

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

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

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


1
@ abbath0767 Ви бачили посилання на це? Можливо, вам буде корисно.
Кішан Соланкі

Я думав, що я вже спробував усе, дякую дуже, не сподівався, що знайду відповідь, яку я шукав.
BekaBot

1
Задоволення @BekaBot
Kishan Solanki

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 (рівень 28 API) вводить нові обмеження на використання не-SDK-інтерфейсів, і це не спрацює, якщо націлити 28. developer.android.com/about/versions/pie/…
ernestkamara

2

оновіть свою бібліотеку підтримки до 28.0.0.

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

1

Якщо ви використовуєте підтримку: design: 28.0.0, додайте цей рядок додаток: labelVisibilityMode = "unlabeled" у свій BottomNavigationView


0

просто хочу додати, що вище цього методу disabledShiftMode також додайте код нижче. @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.