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 на с меткой