BottomNavigationView - Как снять отметку со всех пунктов меню и отобразить заголовки?

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

Я взял этот пост в качестве ориентира.

Согласно документации BottomNavigationView, его целью является

обеспечить быструю навигацию между представлениями верхнего уровня приложения. Он в первую очередь предназначен для использования на мобильных устройствах.

В моем случае я просто хочу, чтобы каждый MenuItem запускал действие, но по умолчанию всегда выбирается один MenuItem:

enter image description here

Я попытался установить цвет на белый с помощью:

app:itemIconTint="@color/white"
app:itemTextColor="@color/white"

Тем не менее, заметно выбранный MenuItem отличается от других (размер заголовка больше), что все еще беспокоит меня:

enter image description here

Я пришел с идеей разместить скрытый элемент MenuItem чтобы выбрать как:

<item
android:id="@+id/uncheckedItem"
android:title="" />

и сделать свой взгляд GONE

 bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
 bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);

Это делает все элементы MenuItem неконтролируемыми, но по умолчанию BottomNavigationView скрывает заголовки, так как в нем отображается более 3 элементов MenuItem, даже если четвертый MenuItem установлен в GONE:

enter image description here

Таким образом, мой вопрос остается, есть ли в наличии/взломать, чтобы отменить выбор всех MenuItems и сохранить его названия отображаются?

Ответ 1

Я нашел свое собственное решение, слияние моего прогресса с этим сообщением.

Шаги:

  • Обновление proguard-rules.pro и сборка синхронизации
  • Создать помощник для отключения режима сдвига BottomNavigationView
  • Создайте элемент, чтобы скрыть его в Menu.xml
  • Inflate BottomNavigationView
  • Установить элемент, который будет скрыт как Проверено GONE
  • Использовать помощник для отключения режима переключения.

Вывод:

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

Рабочий код:

proguard-rules.pro:

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

BottomNavigationShiftHelper.java:

public class BottomNavigationShiftHelper {

    private final static String TAG = "DEBUG_BOTTOM_NAV_UTIL";

    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);
                // set once again checked value, so view will be updated
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.d(TAG, "Unable to get shift mode field");
        } catch (IllegalAccessException e) {
            Log.d(TAG, "Unable to change value of shift mode");
        }
    }
}

Действие Sample.java:

 private void loadNavigationBar() {
        BottomNavigationView bottomNavigationView = (BottomNavigationView)
                findViewById(R.id.navigation_bar);

        bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
        bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);

        BottomNavigationViewUtils.disableShiftMode(bottomNavigationView);

        bottomNavigationView.setOnNavigationItemSelectedListener(
                new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        switch (item.getItemId()) {
                            case R.id.newList:
                                //Do The Math
                                break;
                            case R.id.loadList:
                                //Do The Math
                                break;
                            case R.id.settings:
                                //Do The Math
                                break;
                        }
                        return false;
                    }
                });
    }

BottomNavigationMenu.xml:

<?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/newList"
        android:enabled="true"
        android:icon="@drawable/new_list"
        android:title="@string/common.button.list.new"
        app:showAsAction="withText" />
    <item
        android:id="@+id/loadList"
        android:enabled="true"
        android:icon="@drawable/load"
        android:title="@string/common.button.list.load"
        app:showAsAction="withText" />
    <item
        android:id="@+id/settings"
        android:enabled="true"
        android:icon="@drawable/settings"
        android:title="@string/common.label.settings"
        app:showAsAction="withText" />
    <item
        android:id="@+id/uncheckedItem"
        android:title="" />
</menu>

BottomNavigationComponent (внутри Activity.xml):

<android.support.design.widget.BottomNavigationView
    android:id="@+id/navigation_bar"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:itemIconTint="@color/white"
    app:itemTextColor="@color/white"
    android:background="@drawable/BottomNavigationMenu.xml"
    app:menu="@menu/supercart_bottom_navigation" />

Ответ 2

mNavigationBottom.getMenu().setGroupCheckable(0, false, true);

Ответ 3

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

Если у вас есть интерес. Нажмите здесь: https://github.com/ittianyu/BottomNavigationViewEx

private void initBottomViewAndLoadFragments(final BottomNavigationViewEx bnve) {
    bnve.enableAnimation(false);
    bnve.enableShiftingMode(false);
    bnve.enableItemShiftingMode(false);

    // use the unchecked color for first item
    bnve.setIconTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));
    bnve.setTextTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));

    bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {

        private boolean firstClick = true;
        private int lastItemId = -1;

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            // restore the color when click
            if (firstClick) {
                firstClick = false;
                bnve.setIconTintList(0, getResources().getColorStateList(R.color.selector_bnv));
                bnve.setTextTintList(0, getResources().getColorStateList(R.color.selector_bnv));
            }

            if (firstClick || lastItemId == -1 || lastItemId != item.getItemId()) {
                lastItemId = item.getItemId();
            } else {
                return false;
            }

            // do stuff
            return fillContent(item.getItemId());
        }
    });
}

- res/color/selector_bnv.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/bnv_checked_white" android:state_checked="true" />
    <item android:color="@color/bnv_unchecked_black" />
</selector>

- res/values ​​/colors.xml

<color name="bnv_checked_white">@android:color/white</color>
<color name="bnv_unchecked_black">@android:color/black</color>

Ответ 4

Чтобы отменить выбор всех элементов, я создал это расширение:

fun BottomNavigationView.uncheckAllItems() {
    menu.setGroupCheckable(0, true, false)
    for (i in 0 until menu.size()) {
        menu.getItem(i).isChecked = false
    }
    menu.setGroupCheckable(0, true, true)
}

menu.setGroupCheckable(0, true, false) делает это возможным. Третий параметр сделал меню не эксклюзивным, и затем в цикле вы изменяете проверенный статус. Чтобы закончить, снова установите эксклюзивное меню.

Вот док

Ответ 5

Ваше решение кажется изменением пространства между элементами

Есть мое решение:

"Просто установите цвет щелчка так же, как цвет un-clicked."

например:

private void changeMenuItemCheckedStateColor(BottomNavigationView bottomNavigationView, String checkedColorHex, String uncheckedColorHex) {
    int checkedColor = Color.parseColor(checkedColorHex);
    int uncheckedColor = Color.parseColor(uncheckedColorHex);

    int[][] states = new int[][] {
            new int[] {-android.R.attr.state_checked}, // unchecked
            new int[] {android.R.attr.state_checked}, // checked

    };

    int[] colors = new int[] {
            uncheckedColor,
            checkedColor
    };

    ColorStateList colorStateList = new ColorStateList(states, colors);

    bottomNavigationView.setItemTextColor(colorStateList);
    bottomNavigationView.setItemIconTintList(colorStateList);

}

если вы хотите удалить все элементы, вы можете

changeMenuItemCheckedStateColor(mBottomNavigationView, "#999999", "#999999");

если вы хотите восстановить настройку цвета, вы можете

changeMenuItemCheckedStateColor(mBottomNavigationView, "FF743A", "999999");

Ответ 6

Это то же самое, что и принятый ответ, за исключением того, что я изменил две строки кода, помеченные ниже. При прохождении через BottomNavigationItemViews я устанавливаю флажок всегда, и я также устанавливаю checkable в false. Это не позволяет изменять элементы меню. Вам все еще нужно это правило proguard:

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

Обновленный код:

    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);
                item.setShiftingMode(false);
                item.setChecked(false); // <--- This line changed
                item.setCheckable(false);  // <-- This line was added
            }
        }
        catch (NoSuchFieldException e)
        {
            Log.e("ERROR NO SUCH FIELD", "Unable to get shift mode field");
        }
        catch (IllegalAccessException e)
        {
            Log.e("ERROR ILLEGAL ALG", "Unable to change value of shift mode");
        }

   }

Ответ 7

Мне тоже нужно было, но есть простой способ добиться этого: просто добавьте xml меню в группу и сделайте его checkableBehavior ни к чему;)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="@layout/activity_main">
    <group android:checkableBehavior="none">
        <item
            android:icon="@drawable/ic_back_24dp"
            android:title="back"
            android:id="@+id/navigation_back"/>
        <item
            android:icon="@drawable/ic_check_box_24dp"
            android:title="check"
            android:id="@+id/navigation_check"/>
        <item
            android:icon="@drawable/ic_forward_24dp"
            android:title="forward"
            android:id="@+id/navigation_forward"/>
    </group>
</menu>

Ответ 8

Лучший ответ mNavigationBottom.getMenu().setGroupCheckable(0, false, true) у меня не сработал. Первый элемент все еще показывался как выбранный.

Что сработало для меня, так это наличие невидимого предмета и его выбор, точно так же, как вы делали в вопросе.

Добавьте app:labelVisibilityMode="labeled" в BottomNavigationView чтобы все элементы оставались на виду со своими заголовками.

Ответ 9

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

Я упомянул здесь Пользовательский TextSize поддержки BottomNavigationView Android

В вашем измерении .xml вы можете поместить:

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

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

Установите этот код в методе onCreate, где инициализируется нижний вид навигации

mNavigationBottom.getMenu().setGroupCheckable(0, false, true);

и Last установите нижнюю панель навигации следующим образом:

 <com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:layout_gravity="bottom"
    android:background="?android:attr/windowBackground"
    android:fitsSystemWindows="true"
    app:labelVisibilityMode="labeled"
    app:layout_anchorGravity="fill"
    app:menu="@menu/bottom_nav_menu" />

В этом случае установите приложение: labelVisibilityMode на с меткой