【问题标题】:BottomNavigationView - How to uncheck all MenuItems and keep Titles being displayed?BottomNavigationView - 如何取消选中所有菜单项并保持标题显示?
【发布时间】:2017-05-13 08:11:42
【问题描述】:

由于我喜欢 BottomNavigationView 的设计,我决定用它为我的应用程序实现一个新菜单,而不仅仅是使用简单的按钮。

我以this 的帖子为指导。

根据BottomNavigationViewdocumentation,其目的是为了

在应用的顶级视图之间提供快速导航。它是 主要设计用于移动设备。

就我而言,我只希望每个MenuItem 启动一个活动,但默认情况下总是选择一个MenuItem

我尝试将颜色设置为白色:

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

不过,明显选中的MenuItem 与其他人不同(标题更大),这仍然困扰着我:

我的想法是放置一个隐藏的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);

这会取消选中所有 MenuItems,但默认情况下 BottomNavigationView 会隐藏 Titles,因为它有超过 3 个 MenuItems 要显示,即使第四个 MenuItem 设置为 GONE

所以我的问题仍然存在,是否可以取消选择所有 MenuItem 并保持其标题显示?

【问题讨论】:

  • 您做得对,但需要向您的BottomNavigationView 添加一个属性。看我的回答。
  • 请通过将“uncheckedItem”的可见性设置为 false 来尝试我的答案。在 xml 菜单中,而不是以编程方式进行

标签: android title menuitem bottomnavigationview


【解决方案1】:
mNavigationBottom.getMenu().setGroupCheckable(0, false, true);

【讨论】:

  • 这会取消选择所有项目而没有任何副作用。但是,您必须稍后输入“mNavigationBottom.getMenu().setGroupCheckable(0, true, true);”某处允许项目再次显示为选中状态。
【解决方案2】:

要取消选择我创建此扩展程序的所有项目:

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) 使它成为可能。 第三个参数使菜单不独占,然后在循环中更改选中状态。 完成后再次将菜单设置为独占。

Here the doc

【讨论】:

  • 这就是我想要的。所有菜单都未选中。
  • 就是这样
【解决方案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】:

我找到了自己的解决方案,将我的进度与this 帖子合并。

步骤:

  1. 更新 proguard-rules.pro 并同步构建
  2. 创建 Helper 以禁用 BottomNavigationView 切换模式
  3. 创建要在 Menu.xml 上隐藏的项目
  4. 膨胀底部导航视图
  5. 将要隐藏的项目设置为 Checked GONE
  6. 使用 Helper 禁用换档模式

输出:

工作代码:

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

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

【讨论】:

  • 它可以工作,但现在我的底部导航视图没有占用所有宽度...请您帮忙
  • 我有 5 个项目,如果我添加一个空项目,我会收到此错误:BottomNavigationView 支持的最大项目数为 5
  • @Kusan,在下面查看我的答案。希望它对你有用stackoverflow.com/a/46491753/1236327
  • 我在调整这个菜单上浪费了太多时间,我找到了更好的方法(不理想),我现在为每个用户类使用不同的菜单资源
【解决方案5】:

您的解决方案似乎改变了项目之间的空间

有我的解决方案:

“只需​​将点击的颜色设置为与未点击的颜色相同。”

例如:

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

    接受的答案有一个例外,我们设置了我们无法实现该代码的最大项目。所以我得到了一个比接受的代码更简单的代码,它也适用于最大项目。

    我从这里提到Custom TextSize of BottomNavigationView support android

    在你的 dimen.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 的内部类使用的默认值 dimen。所以要小心。

    在底部导航视图初始化的 onCreate 方法中设置此代码

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

    最后设置你的底部导航栏是这样的:

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

    在此将您的 app:labelVisibilityMode 设置为 labeled

    【讨论】:

      【解决方案7】:

      试试这个,它对我有用

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

      设置

      bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
      

      您将所有菜单项视图都设为未选中;因为选择是针对不可见的uncheckedItem 给出的

      希望对你有所帮助。

      【讨论】:

      • 仅当您在底部导航菜单中使用少于最多 5 个项目时才有效,因此您需要使用其中 1 个菜单项作为不可见项 (android:visible="false")
      【解决方案8】:

      这与接受的答案相同,只是我更改了下面标记的两行代码。当循环通过 BottomNavigationItemViews 时,我将 checkable 设置为 false,并且我还将 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");
              }
      
         }
      

      【讨论】:

        【解决方案9】:

        最佳答案mNavigationBottom.getMenu().setGroupCheckable(0, false, true) 对我不起作用。它仍然显示第一个项目被选中。

        对我有用的是拥有一个不可见的项目并选择它,就像你在问题中所做的那样。

        app:labelVisibilityMode="labeled" 添加到您的BottomNavigationView,以便所有项目及其标题都在视图中。

        【讨论】:

          【解决方案10】:
              if(isDarkMode(context)) {
                  mBotNavView.setItemIconTintList(ColorStateList.valueOf(Color.parseColor("#FFFFFF")));
              } else {
                  mBotNavView.setItemIconTintList(ColorStateList.valueOf(Color.parseColor("#000000")));
              }
          
              public boolean isDarkMode(Context context) {
                  int nightModeFlags = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
                  return darkMode = (nightModeFlags == Configuration.UI_MODE_NIGHT_YES);
              }
          

          【讨论】:

            猜你喜欢
            • 2018-08-19
            • 1970-01-01
            • 2019-01-29
            • 2017-05-18
            • 2014-05-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多