更改从xml布局制作的工具栏菜单上的菜单项
因此,我的应用程序中有此工具栏,并且我想根据用户是否登录显示不同的菜单项。当用户登录或注销时,我想更新我的布局,现在是用于表示更改的工具栏菜单。不过,出于某种原因,我的菜单项根本不会被删除,无论登录状态如何,它们都始终可见。更改从xml布局制作的工具栏菜单上的菜单项
我的菜单项:
<menu
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_add"
android:icon="@drawable/ic_action_add"
android:title="@string/action_add"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_login"
android:icon="@drawable/ic_action_logged_out"
android:title="@string/action_log_in"
app:showAsAction="always"/>
<item
android:id="@+id/action_logout"
android:icon="@drawable/ic_action_logged_in"
android:title="@string/action_log_out"
app:showAsAction="always"/>
</menu>
第一个菜单项是只应该是已登录用户可见此外,我想这是自我解释,但我只希望在日志的一个输入/输出。取决于登录状态,按钮是可见的。
我的Java代码:
protected void initializeToolbar(){
myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
menu = myToolbar.getMenu();
resetToolbarMenu();
myToolbar.setOnMenuItemClickListener(this);
}
private void resetToolbarMenu(){
menu.clear();
getMenuInflater().inflate(R.menu.menu, menu);
if(loginPrefs.getBoolean("login", false)) { //loginPrefs is reference to a SharedPreference object
menu.removeItem(1);
} else {
menu.removeItem(2);
menu.removeItem(0);
}
}
原因我有两种方法,我只是想设置工具栏和侦听一次,但我希望能够每一次改变菜单的用户登录/ out,无需重新加载页面。
成功登录后,将再次调用resetToolbarMenu()
方法。
我猜想menu.remove(0)
不更新的用户界面,但我无法找到另一种方式,而不先膨胀,然后从工具栏得到它达到我的菜单对象,我认为通胀是什么决定什么项目都可见。基本上,我无法找到一种方式来删除任何菜单项,然后以另一种方式膨胀或更新UI。
解决方案:
我改变了我的Java代码弄成这个样子:
protected void initializeToolbar(){
myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu); // Don't know if this is necessary or if returning true is prefered.
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(loginPrefs.getBoolean("login", false)) {
menu.getItem(0).setVisible(true);
menu.getItem(1).setVisible(false);
menu.getItem(2).setVisible(true);
} else {
menu.getItem(0).setVisible(false);
menu.getItem(1).setVisible(true);
menu.getItem(2).setVisible(false);
}
return true;
}
我也只好打电话invalidateOptionsMenu()
上注销/登录更新工具栏/菜单。但是,无论何时打开工具栏上未显示的项目的菜单,onPrepareOptionsMenu()也会自动调用。
PS:OnCreateOptionsMenu
和OnPrepareOptionsMenu
将不会被使用,除非您记得我忘了setSupportActionBar(myToolbar)
。
您可以通过覆盖onCreateOptionsMenu
来创建选项菜单。您可以创建2个xml并根据您的逻辑给它们中的任何一个充气。要强制重画菜单,您可以拨打invalidateOptionsMenu
。
例如
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
if (login) {
inflater.inflate(R.menu.login_menu, menu);
} else {
inflater.inflate(R.menu.logout_menu, menu);
}
return true;
}
与外界变化的标志和强制重绘
login = false; // or true
invalidateOptionsMenu();
您必须在活动中覆盖onPrepareOptionsMenu以更改菜单中的项目。
从文档:
准备要显示的屏幕的标准选项菜单。在菜单显示之前,每当显示菜单时都会调用它。您可以使用此方法高效地启用/禁用项目或以其他方式动态修改内容。
所以我会提出我的代码去除物品进入该方法,然后将项目将适当每次准备我尝试夸大菜单?或者我使用其他答案中的invalidateOptionsMenu方法强制此方法运行?文档不给迷惑人的任何例子:/ – Chexxor
这个方法总是被调用,你不必无效。如果您使用无效,则强制它再次调用onCreateOptionsMenu。您应该使用invalidateOptionsMenu如果你想夸大另外一个,像一个完全不同的XML,如果你只是想删除一些项目,做它onPrepareOptionsMenu – bogdanN
所以我把它所有的工作。但onPrepareOptionsMenu只有当我按下工具栏/菜单上的东西时才被调用。为了在登录/注销时更新它,我使用了invalidateOptionsMenu。也许有一种更好的方法来强制prepare方法而不用再次调用create方法,但现在无效似乎为我做了。 – Chexxor
我正在寻找比静态定义两种布局更动态的东西。如果我已经在活动增加新的东西,我不想任何显示添加项目,这将使其成为4个不同的XML文件,而不是2,肯定能查这个事情OptionsMenu不过。 – Chexxor
动态菜单的相同方法。您需要使用menu.add在onCreateOptionsMenu中创建菜单,而不是膨胀静态布局。并强制重绘使用invalidateOptionsMenu – tompee
嗯。这将迫使我以编程方式定义菜单项目,看起来像?有没有办法来加载XML菜单作为一个对象,然后通过使用menu.remove(INT)后,该对象膨胀? – Chexxor