NavigationView 菜单不更新

NavigationView menu does not update

我在这里写的是我们从 AppCompat 库迁移到 AndroidX 库时引入的一个问题。在这样做的同时,我们从 android.support.design.widget.NavigationView 切换到 com.google.android.material.navigation.NavigationView,这就是以下问题开始的时候。

在我们的 NavigationView 设计中,为了节省 space,我们实现了一个可扩展的菜单,以便当用户单击“更多”按钮时,菜单会扩展以显示更多选项。一开始只有部分选项可见,其余的不可见,如下;



点击“更多...”按钮后,菜单展开为;



为此,我们使用了以下代码;

@Override
public boolean onNavigationItemSelected(MenuItem item)
{
    ....
    if (item.getItemId() == R.id.nav_more)
    {
        item.setVisible(false); // hide the “More” item
        getMenu().findItem(R.id.nav_option_3).setVisible(true);
        getMenu().findItem(R.id.nav_option_4).setVisible(true);
        getMenu().findItem(R.id.nav_option_5).setVisible(true);
        getMenu().findItem(R.id.nav_option_6).setVisible(true);
        return true;
    }
    .......
    return false;
}

好吧,这段代码过去一直有效,但是当我们迁移到使用 androidx 库时,噗,它停止了工作。好吧,它确实起作用了。 “更多...”按钮被隐藏,但之前隐藏的选项没有显示。 因为,我花了很多时间来解决这个问题,为了让其他人免于头痛,我将解释这个问题和解决方案。

在这种情况下,首先要做的是查看源代码。由于代码是开源的,我能够在 github 获得它。乍一看,我并没有变得更聪明。我发现 NavigationView has a NavigationMenuPresenter object field (called presenter), that has a method called updateMenuView() which calls adapter.update(), which calls prepareMenuItems()notifyDataSetChanged()。这听起来像是需要的修复,所以使用反射,我们访问并调用了 updateMenuView() 方法,但令人惊讶的是,它没有帮助!

所以,我决定把它发挥到极致,看看如果我调用 getMenu().clear() 会发生什么,信不信由你,什么也没发生。似乎在显示 NavigationView 之后对 菜单所做的任何更改都被忽略了。但是快速浏览一下源代码,我看不出任何原因。

那么我该如何解决这个问题呢?我尝试使用该库的最新 alpha 版本,但我仍然遇到同样的问题。

好吧,经过大量工作,我找到了解决方案。其实很简单。等待答案。

Lionscribe

所以我回到源代码,寻找一些线索,当我偶然发现一个名为 setUpdateSuspended(boolean updateSuspended). Well, that sounded suspicious! I searched for usage of this method, and found it being called in the onClick 回调的方法时。这是代码的最小化版本;

@Override
    public void onClick(View view) {
      NavigationMenuItemView itemView = (NavigationMenuItemView) view;
      setUpdateSuspended(true);
      MenuItemImpl item = itemView.getItemData();
      boolean result = menu.performItemAction(item, NavigationMenuPresenter.this, 0);
      setUpdateSuspended(false);
  }

宾果!似乎在处理点击时,NavigationView 暂停并且不会识别对菜单所做的任何更改。我不确定这样做的原因,但是当我们在 onNavigationItemSelected 回调中更新菜单时,由 onClick 方法调用,菜单更新被忽略。

好吧,一旦我理解了这个问题,解决方案就简单明了。我只是将代码包装在 Runnable 中并发布,以便它在 之后运行 onClick 方法 returns 和 setUpdateSuspended 设置回 false。这是更新后的代码;

@Override
public boolean onNavigationItemSelected(MenuItem item)
{
    ....
    if (item.getItemId() == R.id.nav_more)
    {
        final MenuItem itemFinal = item;
        post(new Runnable()
        {
            @Override
            public void run()
            {
                    getMenu().findItem(R.id.nav_option_3).setVisible(true);
                    getMenu().findItem(R.id.nav_option_4).setVisible(true);
                    getMenu().findItem(R.id.nav_option_5).setVisible(true);
                    getMenu().findItem(R.id.nav_option_6).setVisible(true);
                    itemFinal.setVisible(false);  // hide the “More” item
            }
        });
        return true;
    }
    .......
    return false;
}

中提琴!可扩展菜单现在像以前一样工作,现在显示隐藏的项目!

希望对遇到同样问题的其他人有所帮助。

Lionscribe