如何将项目添加到 NavigationView 中的菜单组
How to add an item to a menu group in NavigationView
在 Android 的文字游戏中,我目前有一个从 left_drawer_menu.xml
扩展而来的硬编码菜单,由 3 组组成(我的回合,对手的回合,最后是其他内容):
mLeftDrawer = (NavigationView) findViewById(R.id.left_drawer);
mLeftDrawer.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
Menu menu = mLeftDrawer.getMenu();
if (menuItem.getGroupId() == R.id.my_move) {
menu.setGroupCheckable(R.id.my_move, true, true);
menu.setGroupCheckable(R.id.his_move, false, false);
menu.setGroupCheckable(R.id.extras, false, false);
} else if (menuItem.getGroupId() == R.id.his_move) {
menu.setGroupCheckable(R.id.my_move, false, false);
menu.setGroupCheckable(R.id.his_move, true, true);
menu.setGroupCheckable(R.id.extras, false, false);
} else if (menuItem.getGroupId() == R.id.extras) {
menu.setGroupCheckable(R.id.my_move, false, false);
menu.setGroupCheckable(R.id.his_move, false, false);
menu.setGroupCheckable(R.id.extras, true, true);
}
menuItem.setChecked(true);
mLeftItem = menuItem.getItemId();
mDrawerLayout.closeDrawer(mLeftDrawer);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mLeftItem == R.id.start) {
startNewGame();
}
}
},DRAWER_CLOSE_DELAY);
return true;
}
});
现在我正在尝试动态更改该菜单。
我有包含所有游戏数据的 SQLite 实例,并使用 IntentService
到 read/write 数据库 - 这部分工作正常。
我目前的难点是:使用下面的代码,新项目被添加到R.id.my_move
组之外:
if (mLeftItem == R.id.start) {
startNewGame();
Random r = new Random();
int i = r.nextInt(100);
menu.add(R.id.my_move, i, i, "Item " + i); // why is my_move ignored?
}
更新:
作为进一步的测试,我尝试使用以下代码将偶数项和偶数项分配给 2 个单独的组:
Random r = new Random();
int i = r.nextInt(100);
int group = 1 + (i % 2); // can be 1 or 2
menu.add(group, i, i, "Item " + i);
然而结果看起来很混乱:
我还发现了(可能已经修复了?)Issue 176300 想知道是否应该使用子菜单而不是菜单组更好?
menu.add(R.id.my_move, i, i, "Item " + i);
您还将订单(第 3 个参数)指定为 i
。我猜这是覆盖了 groupId。尝试将其设置为NONE
,如前所述here
menu.add(R.id.my_move, i, NONE, "Item " + i);
编辑:
可能是这样的
MenuItem lastItem = menu.findItem(R.id.<lastItemId>);
int lastOrder= lastItem.getOrder();
menu.add(R.id.my_move, i, lastOrder-5, "Item " + i);
Order
是类别和顺序的组合,所以它可能不像这样直接。
检查 MenuItemImpl 源代码
...
* @param group Item ordering grouping control. The item will be added after
* all other items whose order is <= this number, and before any
* that are larger than it. This can also be used to define
* groups of items for batch state changes. Normally use 0.
...
MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
CharSequence title, int showAsAction) {
所以你应该在你的 xml 中定义顺序(对一组中的项目给出相同的顺序并在每个后续组中递增)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/my_move" android:checkableBehavior="single">
<item
android:orderInCategory="0"
android:id="@+id/game1"
android:icon="@drawable/ic_stars_black_24dp"
android:title="Game #1" />
<item
android:orderInCategory="0"
android:id="@+id/game2"
android:icon="@drawable/ic_stars_black_24dp"
android:title="Game #2" />
</group>
<group android:id="@+id/his_move" android:checkableBehavior="single">
<item
android:orderInCategory="1"
android:id="@+id/game5"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #5" />
<item
android:orderInCategory="1"
android:id="@+id/game6"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #6" />
<item
android:orderInCategory="1"
android:id="@+id/game7"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #7" />
</group>
.....
</menu>
并在代码中添加项目时给出适当的订单值。因此,如果您想在第一组末尾添加项目,请将其添加为:
menu.add(R.id.my_move, Menu.NONE, 0, "Item1");
如果您想添加到第二组,请将其添加为:
menu.add(R.id.his_move, Menu.NONE, 1, "Item2");
您的代码的问题可能是 xml 中的所有项目都有默认的 orderInCategory 0,因此在之后添加了新项目
所有这些项目。
更新
要为 MenuItem
使用 setIcon
方法添加图标
menu.add(R.id.my_move, Menu.NONE, 0, "Item1").setIcon(R.drawable.ic_stars_black_24dp);
我是这样解决的:
设置菜单:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="my moves"
android:id="@+id/submenu_1">
<menu>
<item
android:id="@+id/my_dummy_item_1"
android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/my_dummy_item_2"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/add_item"
android:icon="@drawable/ic_menu_manage"
android:title="Add Item" />
</menu>
</item>
<item android:title="opponent's moves"
android:id="@+id/submenu_2">
<menu>
<item
android:id="@+id/opponent_dummy_item_1"
android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/opponent_dummy_item_2"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/opponent_dummy_item_3"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</menu>
</item>
</menu>
在onNavigationItemSelected()
中,获取MenuItem
你想通过订单id扩展(或通过findItem()
),然后从中获取 SubMenu
并向其中添加新项目:
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.add_item) {
Random r = new Random();
int i = r.nextInt(100);
MenuItem myMoveGroupItem = navigationView.getMenu().getItem(0);
// MenuItem myMoveGroupItem = navigationView.getMenu().findItem(R.id.submenu_1); -- it also works!
SubMenu subMenu = myMoveGroupItem.getSubMenu();
subMenu.add("Item "+i);
}
return true;
}
希望对你有所帮助
在 Android 的文字游戏中,我目前有一个从 left_drawer_menu.xml
扩展而来的硬编码菜单,由 3 组组成(我的回合,对手的回合,最后是其他内容):
mLeftDrawer = (NavigationView) findViewById(R.id.left_drawer);
mLeftDrawer.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
Menu menu = mLeftDrawer.getMenu();
if (menuItem.getGroupId() == R.id.my_move) {
menu.setGroupCheckable(R.id.my_move, true, true);
menu.setGroupCheckable(R.id.his_move, false, false);
menu.setGroupCheckable(R.id.extras, false, false);
} else if (menuItem.getGroupId() == R.id.his_move) {
menu.setGroupCheckable(R.id.my_move, false, false);
menu.setGroupCheckable(R.id.his_move, true, true);
menu.setGroupCheckable(R.id.extras, false, false);
} else if (menuItem.getGroupId() == R.id.extras) {
menu.setGroupCheckable(R.id.my_move, false, false);
menu.setGroupCheckable(R.id.his_move, false, false);
menu.setGroupCheckable(R.id.extras, true, true);
}
menuItem.setChecked(true);
mLeftItem = menuItem.getItemId();
mDrawerLayout.closeDrawer(mLeftDrawer);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mLeftItem == R.id.start) {
startNewGame();
}
}
},DRAWER_CLOSE_DELAY);
return true;
}
});
现在我正在尝试动态更改该菜单。
我有包含所有游戏数据的 SQLite 实例,并使用 IntentService
到 read/write 数据库 - 这部分工作正常。
我目前的难点是:使用下面的代码,新项目被添加到R.id.my_move
组之外:
if (mLeftItem == R.id.start) {
startNewGame();
Random r = new Random();
int i = r.nextInt(100);
menu.add(R.id.my_move, i, i, "Item " + i); // why is my_move ignored?
}
更新:
作为进一步的测试,我尝试使用以下代码将偶数项和偶数项分配给 2 个单独的组:
Random r = new Random();
int i = r.nextInt(100);
int group = 1 + (i % 2); // can be 1 or 2
menu.add(group, i, i, "Item " + i);
然而结果看起来很混乱:
我还发现了(可能已经修复了?)Issue 176300 想知道是否应该使用子菜单而不是菜单组更好?
menu.add(R.id.my_move, i, i, "Item " + i);
您还将订单(第 3 个参数)指定为 i
。我猜这是覆盖了 groupId。尝试将其设置为NONE
,如前所述here
menu.add(R.id.my_move, i, NONE, "Item " + i);
编辑: 可能是这样的
MenuItem lastItem = menu.findItem(R.id.<lastItemId>);
int lastOrder= lastItem.getOrder();
menu.add(R.id.my_move, i, lastOrder-5, "Item " + i);
Order
是类别和顺序的组合,所以它可能不像这样直接。
检查 MenuItemImpl 源代码
...
* @param group Item ordering grouping control. The item will be added after
* all other items whose order is <= this number, and before any
* that are larger than it. This can also be used to define
* groups of items for batch state changes. Normally use 0.
...
MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
CharSequence title, int showAsAction) {
所以你应该在你的 xml 中定义顺序(对一组中的项目给出相同的顺序并在每个后续组中递增)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/my_move" android:checkableBehavior="single">
<item
android:orderInCategory="0"
android:id="@+id/game1"
android:icon="@drawable/ic_stars_black_24dp"
android:title="Game #1" />
<item
android:orderInCategory="0"
android:id="@+id/game2"
android:icon="@drawable/ic_stars_black_24dp"
android:title="Game #2" />
</group>
<group android:id="@+id/his_move" android:checkableBehavior="single">
<item
android:orderInCategory="1"
android:id="@+id/game5"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #5" />
<item
android:orderInCategory="1"
android:id="@+id/game6"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #6" />
<item
android:orderInCategory="1"
android:id="@+id/game7"
android:icon="@drawable/ic_clock_black_24dp"
android:title="Game #7" />
</group>
.....
</menu>
并在代码中添加项目时给出适当的订单值。因此,如果您想在第一组末尾添加项目,请将其添加为:
menu.add(R.id.my_move, Menu.NONE, 0, "Item1");
如果您想添加到第二组,请将其添加为:
menu.add(R.id.his_move, Menu.NONE, 1, "Item2");
您的代码的问题可能是 xml 中的所有项目都有默认的 orderInCategory 0,因此在之后添加了新项目 所有这些项目。
更新
要为 MenuItem
setIcon
方法添加图标
menu.add(R.id.my_move, Menu.NONE, 0, "Item1").setIcon(R.drawable.ic_stars_black_24dp);
我是这样解决的:
设置菜单:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:title="my moves" android:id="@+id/submenu_1"> <menu> <item android:id="@+id/my_dummy_item_1" android:icon="@drawable/ic_menu_camera" android:title="Import" /> <item android:id="@+id/my_dummy_item_2" android:icon="@drawable/ic_menu_gallery" android:title="Gallery" /> <item android:id="@+id/add_item" android:icon="@drawable/ic_menu_manage" android:title="Add Item" /> </menu> </item> <item android:title="opponent's moves" android:id="@+id/submenu_2"> <menu> <item android:id="@+id/opponent_dummy_item_1" android:icon="@drawable/ic_menu_camera" android:title="Import" /> <item android:id="@+id/opponent_dummy_item_2" android:icon="@drawable/ic_menu_gallery" android:title="Gallery" /> <item android:id="@+id/opponent_dummy_item_3" android:icon="@drawable/ic_menu_manage" android:title="Tools" /> </menu> </item> </menu>
在
onNavigationItemSelected()
中,获取MenuItem
你想通过订单id扩展(或通过findItem()
),然后从中获取SubMenu
并向其中添加新项目:@SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.add_item) { Random r = new Random(); int i = r.nextInt(100); MenuItem myMoveGroupItem = navigationView.getMenu().getItem(0); // MenuItem myMoveGroupItem = navigationView.getMenu().findItem(R.id.submenu_1); -- it also works! SubMenu subMenu = myMoveGroupItem.getSubMenu(); subMenu.add("Item "+i); } return true; }
希望对你有所帮助