2017-05-26 113 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