BottomNavigationView - How do I unmark all menu items and display headings?

Since I liked the design from BottomNavigationView I decided to create a new menu for my application, and not just use simple buttons.

I took this post as a guide.

According to the BottomNavigationView documentation , its purpose is

Provide quick navigation between top-level views of the application. It is primarily intended for use on mobile devices.

In my case, I just want each MenuItem trigger an action, but by default one MenuItem always selected:

enter image description here

I tried setting the color to white with:

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

However, the markedly selected MenuItem is different from the others (the header size is larger), which still bothers me:

enter image description here

I came up with the idea of ​​placing a hidden MenuItem to choose how:

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

and make your look GONE

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

This makes all MenuItem elements uncontrollable, but by default BottomNavigationView hides the headers because it displays more than 3 MenuItem elements, even if the fourth MenuItem set to GONE :

enter image description here

So my question remains, is there a hack / hack to deselect all MenuItems and keep its names displayed?

+12
source share
9 answers

I found my own solution, merging my progress with this post.

Steps:

  • Update proguard-rules.pro and build sync
  • Create an assistant to disable the shift mode. BottomNavigationView
  • Create an element to hide it in Menu.xml
  • Inflate BottomNavigationView
  • Set the item to be hidden as GONE Checked
  • Use an assistant to turn off switching mode.

Output:

enter image description here

Work code:

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

  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 (inside 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" /> 
+3
source
 mNavigationBottom.getMenu().setGroupCheckable(0, false, true); 
+18
source

Thanks for your idea. I implemented it in my library. I have a better way to do this, after thinking. Therefore, it will not show space.

If you have any interest. Click here: 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> 
+5
source

To deselect all items, I created this extension:

 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) makes this possible. The third parameter made the menu non-exclusive, and then in the loop you change the checked status. To finish, set the exclusive menu again.

Here is the dock

+4
source

Your decision seems to change the space between the elements

There is my solution:

"Just set the color of the click just like the color of un-clicked."

eg:

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

if you want to delete all items you can

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

if you want to restore the color setting you can

 changeMenuItemCheckedStateColor(mBottomNavigationView, "FF743A", "999999"); 
+2
source

This is the same as the accepted answer, except that I changed the two lines of code marked below. When passing through BottomNavigationItemViews, I always check the box, and I also set checkable to false. This does not allow changing menu items. You still need this proguard rule:

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

Updated code:

  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"); } } 
0
source

I needed it too, but there is an easy way to achieve this: just add the xml menu to the group and make it checkableBehavior to nothing;)

 <?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> 
0
source

The best answer is mNavigationBottom.getMenu().setGroupCheckable(0, false, true) did not work for me. The first item was still showing as selected.

What worked for me was the presence of an invisible item and its selection, just like you did in the question.

Add app:labelVisibilityMode="labeled" to the BottomNavigationView so that all items remain visible with their headers.

0
source

There is an exception in the accepted answer: we set the maximum element that we cannot implement in this code. So, I got a code simpler than the accepted code, and it also works with the maximum element.

I mentioned here Custom TextSize support Android BottomNavigationView

In your .xml dimension you can put:

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

By doing this, you override the default dimension that the internal BottomNavigationView classes use. So be careful.

Set this code in the onCreate method, where the bottom navigation view is initialized

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

and Last, set the bottom navigation bar as follows:

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

In this case, install the application: labelVisibilityMode on with label

0
source

Source: https://habr.com/ru/post/1265454/


All Articles