2017-05-26 98 views
1

因此,我的应用程序中有此工具栏,并且我想根据用户是否登录显示不同的菜单项。当用户登录或注销时,我想更新我的布局,现在是用于表示更改的工具栏菜单。不过,出于某种原因,我的菜单项根本不会被删除,无论登录状态如何,它们都始终可见。更改从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:OnCreateOptionsMenuOnPrepareOptionsMenu将不会被使用,除非您记得我忘了setSupportActionBar(myToolbar)

回答

1

您可以通过覆盖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(); 
+0

我正在寻找比静态定义两种布局更动态的东西。如果我已经在活动增加新的东西,我不想任何显示添加项目,这将使其成为4个不同的XML文件,而不是2,肯定能查这个事情OptionsMenu不过。 – Chexxor

+0

动态菜单的相同方法。您需要使用menu.add在onCreateOptionsMenu中创建菜单,而不是膨胀静态布局。并强制重绘使用invalidateOptionsMenu – tompee

+0

嗯。这将迫使我以编程方式定义菜单项目,看起来像?有没有办法来加载XML菜单作为一个对象,然后通过使用menu.remove(INT)后,该对象膨胀? – Chexxor

1

您必须在活动中覆盖onPrepareOptionsMenu以更改菜单中的项目。

从文档:

准备要显示的屏幕的标准选项菜单。在菜单显示之前,每当显示菜单时都会调用它。您可以使用此方法高效地启用/禁用项目或以其他方式动态修改内容。

+0

所以我会提出我的代码去除物品进入该方法,然后将项目将适当每次准备我尝试夸大菜单?或者我使用其他答案中的invalidateOptionsMenu方法强制此方法运行?文档不给迷惑人的任何例子:/ – Chexxor

+0

这个方法总是被调用,你不必无效。如果您使用无效,则强制它再次调用onCreateOptionsMenu。您应该使用invalidateOptionsMenu如果你想夸大另外一个,像一个完全不同的XML,如果你只是想删除一些项目,做它onPrepareOptionsMenu – bogdanN

+0

所以我把它所有的工作。但onPrepareOptionsMenu只有当我按下工具栏/菜单上的东西时才被调用。为了在登录/注销时更新它,我使用了invalidateOptionsMenu。也许有一种更好的方法来强制prepare方法而不用再次调用create方法,但现在无效似乎为我做了。 – Chexxor