BottomNavigationView с более чем 3 элементами: заголовок вкладки скрывается


85

Я использую BottomNavigationView с использованием Android Support Desing Library 25. Но когда я переключаю вкладки, название другой вкладки скрывается. Но в самом нижнем навигационном представлении нет скрытой проблемы. Но мой прячется.

MyBottomNavigation

Но я хочу, чтобы это выглядело именно так. Есть идеи сделать это? Что мне не хватает?

ActualBottomNavigation

Вот мой код:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.yunus.ototakip.MainActivity">

<FrameLayout
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/bottom_navigation"
    android:layout_alignParentTop="true">
</FrameLayout>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@color/beyaz"
    app:itemTextColor="@color/beyaz"
    app:menu="@menu/bottombar_menu" />

bottom_bar_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
 <item
android:id="@+id/bb_menu_arac"
android:enabled="true"
android:icon="@drawable/icon_car"
android:title="@string/araclarim"
app:showAsAction="ifRoom" />
 <item
android:id="@+id/bb_menu_yakin"
android:enabled="true"
android:icon="@drawable/icon_yer"
android:title="@string/yakinimdakiler"
app:showAsAction="ifRoom" />
  <item
android:id="@+id/bb_menu_yaklasan"
android:enabled="true"
android:icon="@drawable/icon_takvim"
android:title="@string/yaklasanlar"
app:showAsAction="ifRoom" />

<item
    android:id="@+id/bb_menu_ipucu"
    android:enabled="true"
    android:icon="@drawable/icon_ipucu"
    android:title="@string/ipuclari"
    app:showAsAction="ifRoom" />
 </menu>

ты пробовал app:showAsAction="alwaysвместоifRoom
Яссин БЕЛДИ

Я пробовал, но это все еще скрывается
Юнус Хазнедар


1
@YunusHaznedar, если предмета больше 3, текст всегда будет
Шашанк Верма

1
Привет, @DanXPrado, спасибо, что поделились решением. Я пометил ваш ответ как принятый. Удачного кодирования.
Юнус Хазнедар

Ответы:


143

Решение с использованием отражения больше не работает, поскольку поле mShiftingMode было удалено.

Сейчас есть простой способ сделать это: использовать библиотеку поддержки 28 или выше и просто добавить app:labelVisibilityMode="labeled"в свое BottomNavigationViewобъявление XML.

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


Работает как чемпион, но как сделать его с возможностью круговой прокрутки?
Шайлендра Мадда

@ShylendraMadda Я предлагаю вам опубликовать это как новый вопрос, поскольку он не связан с этим вопросом.
Данило Прадо

1
Как это не поведение по умолчанию ... Я потратил несколько часов на app: showAsAction, android: visible, android: enabled и множество других хаков. Благодаря!
Danish Khan

94

ОБНОВИТЬ

removeShiftMode () больше не требуется, так как в библиотеке поддержки 28.0.0-alpha1 теперь мы можем добавлять метки .

В XML:

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

Для программного изменения:

mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); 

Чтобы это работало: обновите библиотеку поддержки дизайна до 28.0.0-alpha1.

Вот хорошее чтение

ДЛЯ СТАРЫХ БИБЛИОТЕК ПОДДЕРЖКИ:

в вашем bottom_bar_menu.xml.Измените showAsActionатрибут

<item android:id="@id/menu_item"
android:title="text"
android:icon="@drawable/drawable_resource_name"
android:showAsAction="always|withText" />

в build.gradle:

compile 'com.android.support:design:25.3.1'

НИЖНЯЯ НАВИГАЦИЯ ПРОСМОТРЕТЬ БОЛЕЕ 3 ЭЛЕМЕНТОВ: используйте removeShiftMode() метод

в BottomNavigationViewHelper.javaиспользовании:

import android.annotation.SuppressLint;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import java.lang.reflect.Field;

    public class BottomNavigationViewHelper {
        @SuppressLint("RestrictedApi")
        public static void removeShiftMode(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("BottomNav", "Unable to get shift mode field", e);
            } catch (IllegalAccessException e) {
                Log.e("BottomNav", "Unable to change value of shift mode", e);
            }
        }
    }

Назовите это, используя:

BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_navigation);
BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

Это отключит анимацию сдвига текста заголовка и включит отображение текста.


2
Нет, все еще скрывается. Я пробовал «всегда» и «всегда | withText»
Юнус Хазнедар

1
один из заголовков вашего элемента большой, что приводит к блокировке просмотра другим? попробуйте с маленькими заголовками и рисунками ..
rafsanahmad007

1
см. эту строчку в учебном материале, за которым вы It’s important to note that the maximum number of items we can display is 5. This may change at any point, so it’s important to check this by using the getMaxItem() method provided by the BottomNavigationView class rather than hard-coding the value yourself.
следите

1
отличный ответ, спасибо
Хамза Абдулла

2
Решение для отражения работает довольно хорошо com.android.support:design:25.4.0, но не работает com.android.support:design:26.1.0, поэтому я немного откатываю целевой SDK и версию зависимостей.
Evi Song

10

После сканирования исходного кода BottomNavigationView я нахожу

mShiftingMode = mMenu.size() > 3;

в строке 265 BottomNavigationMenuView.java это означает, что если размер меню больше 3, заголовок вкладки будет скрыт. Поэтому, если вы хотите отобразить заголовок вкладки, вам просто нужно получить код из сборки и изменить его ниже.

mShiftingMode = mMenu.size() > 5;

PS: максимальное количество вкладок в BottonNavigationView должно быть от 3 до 5. Вы можете получить код на BottomNavigationViewNew. введите описание изображения здесь


У меня есть собственный CustomBottomView, который расширяет BottomNavigationView, есть ли способ вместо этого установить это свойство?
JPM

1
Я не вижу строки «BottomNavigationMenuView», которая касается ограничения в 3 вкладки. Может код поменяли?
разработчик Android

8

Создать класс BottomNavigationViewHelper

import android.annotation.SuppressLint;
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 {
    @SuppressLint("RestrictedApi")
    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);
if(menuView.getChildCount()<6)
           {
            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);
        }
    }
}   

Вызов

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

1
У него есть SuppressLint, который решает проблему аннотации restrictAPI
code4j

3

Функция расширения Kotlin:

@SuppressLint("RestrictedApi")
fun BottomNavigationView.removeShiftMode(){
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView.javaClass.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) {
        e.printStackTrace()
        Timber.tag("BottomNav").e( e, "Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.tag("BottomNav").e( e, "Unable to change value of shift mode")
    }
}

Спасибо, сэр. Очень признателен.
Юнус Хазнедар

1
item.setShiftingMode(false)сейчасitem.setShifting(false)
Sim

2

Я в значительной степени использовал ответ rafsanahmad007, но перевел его на Котлин. Разрешите поделиться с будущими странниками

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
        shiftingMode.setAccessible(true)
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.setAccessible(false)
        for (i in 0..(menuView.childCount - 1)) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.getItemData().isChecked())
        }
    } catch (e: NoSuchFieldException) {
        Timber.e("Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.e("Unable to change value of shift mode")
    }
}

1
Это решение уже недействительно, принятое решение правильное от @DanXPrado
jpardogo

Спасибо, что сообщили мне
Karma Maker

1

Следует отметить одно, даже если это не применимо в данном случае.

Этот шаблон можно использовать, когда у вас есть от 3 до 5 пунктов назначения верхнего уровня для навигации.

Чтобы включить отображение заголовка значка, выполните следующие действия:

  1. Убедитесь, что XML-код вашего элемента меню (bottom_navigation_menu) имеет следующую структуру: -

    <item
        android:id="@+id/action_home"
        android:enabled="true"
        android:icon="@drawable/ic_action_home"
        android:title="HOME"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_favourites"
        android:enabled="true"
        android:icon="@drawable/ic_action_favourite"
        android:title="FAVOURITES"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_basket"
        android:enabled="true"
        android:icon="@drawable/ic_action_basket"
        android:title="BASKET"
        app:showAsAction="ifRoom"/>
    

  2. Добавьте в приложение кода BottomNavigationView следующее: labelVisibilityMode = "labeled"

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@android:color/white"
    app:itemIconTint="@android:color/black"
    app:itemTextColor="@android:color/black"
    app:menu="@menu/bottom_navigation_menu"
    app:labelVisibilityMode="labeled"/>


0

У меня это работает в API 26:

 navigation = (BottomNavigationView) view.findViewById(R.id.bottom_navigation);


     try{disableShiftMode(navigation);}catch(Exception ew){}

Сделайте этот метод в своей деятельности или фрагменте, куда вы хотите вызвать:

 @SuppressLint("RestrictedApi")
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);
            item.setShiftingMode(false);

            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {

    } catch (IllegalAccessException e) {

    }
}

0

Вы можете использовать это для отображения текста и значков в 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>

Мне помогли эти ссылки и ссылки. Вы также можете получить помощь, изучив эти ссылки. Это мне очень помогает. Надеюсь, это также поможет вам. Благодаря....


0

быстрое исправление, просто добавьте приложение: labelVisibilityMode = "с надписью" в xml

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@drawable/bottom_navigation_color_selector"
    app:itemTextColor="@drawable/bottom_navigation_color_selector"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/menu_bottom_navigation" />

Запись

  implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.