Jak ukryć element menu na pasku akcji?


Odpowiedzi:


484

Uzyskaj MenuItemwskazanie na taki element, przywołaj setVisiblego, aby dostosować jego widoczność, a następnie przywołaj invalidateOptionsMenu()swoją aktywność, aby odpowiednio dostosować menu ActionBar.

Aktualizacja: A MenuItemnie jest zwykłym widokiem, który jest częścią twojego układu. To coś wyjątkowego, zupełnie innego. Twój kod wraca nulldo item, co powoduje awarię. Zamiast tego musisz zrobić:

MenuItem item = menu.findItem(R.id.addAction);

Oto sekwencja, w której powinieneś zadzwonić: najpierw zadzwoń, invalidateOptionsMenu()a następnie w środku onCreateOptionsMenu(Menu)uzyskaj odwołanie do MenuItem (dzwoniąc menu.findItem()) i zadzwoń setVisible()do niego


O tym początkowo myślałem, ale powoduje to awarię aplikacji.
Stir Zoltán

3
@Stir Zoltán: Cóż, tak to robisz, możesz zrobić to źle, jeśli spowoduje to awarię aplikacji. Na przykład MenuItemmoże być nulltak, ponieważ używasz getItemzamiast findItem. Nigdy nie moglibyśmy wiedzieć, nie widząc zarówno kodu, jak i dziennika awarii.
K-ballo

OK, ale jak mogę uzyskać odniesienie do menu poza metodą onCreateOptionsMenu?
Stir Zoltán

7
@Stir Zoltán: Uważam, że ten komentarz nie ma sensu ... Po prostu odnieś się do pozycji menu w onCreateOptionsMenui ustaw widoczność pozycji w tym momencie. Lub zachowaj referencję, dopóki nie zdecydujesz, czy powinna być widoczna, czy nie.
K-ballo

33
Myślę, że (co najwyżej) ta odpowiedź jest źle sformułowana, ponieważ kolejność kroków jest nieprawidłowa. Prawidłowa sekwencja polega na pierwszym wywołaniu, invalidateOptionsMenu()a następnie w środku, onCreateOptionsMenu(Menu)uzyskaniu odniesienia do MenuItem(przez wywołanie menu.findItem()) i wywołaniu setVisible()go. Odpowiedzi suhas_sm i P1r4nh4 przedstawiają prawidłowe podejście.
Ted Hopp

163

Znaleziono uzupełnienie do tego pytania:

Jeśli chcesz zmienić widoczność elementów menu w podróży, wystarczy ustawić zmienną członka w swojej aktywności, aby pamiętać, że chcesz ukryć menu i wywołać invalidateOptionsMenu()i ukryć elementy w przesłoniętej onCreateOptionsMenu(...)metodzie.

//anywhere in your code
...
mState = HIDE_MENU; // setting state
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == HIDE_MENU)
    {
        for (int i = 0; i < menu.size(); i++)
            menu.getItem(i).setVisible(false);
    }
}

W moim przykładzie ukryłem wszystkie przedmioty.


2
Właśnie tego szukałem. trzymanie się MenuItem i wywoływanie setVisible () nie wydawało się robić tego, czego się spodziewałem (może dlatego, że wywoływałem invalidateOptionsMenu () po tym, przebudowując menu), ale tak czy inaczej - działa dokładnie tak, jak miałem nadzieję, dzięki!
Matt

4
Jeśli chcesz ukryć każdy przedmiot, istnieje łatwiejszy sposób. Zamiast zapętlać tutaj każdy element, możesz po prostu zrobić: if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }Dokumenty mówią: „Musisz zwrócić wartość true, aby menu było wyświetlane; jeśli zwrócisz wartość false, nie zostanie wyświetlone”.
w3bshark,

Chciałbym również wspomnieć, że takie podejście jest znacznie czystsze niż zaakceptowana odpowiedź. Dzięki za udostępnienie!
w3bshark,

przez wywołanie invalidateOptionMenu () wywołany onCreateOptionMenu () i obsłużę moje warunki w onCreateOptionMenu (). Dzięki za dobrą odpowiedź
użytkownik1912026

onPrepareOptionsMenu()powinien być używany do wyświetlania / ukrywania logiki zamiast, onCreateOptionsMenu()ponieważ jest wywoływany tylko raz, więc nie jest użyteczny, jeśli chcesz zmienić elementy menu po jego inicjalizacji. Więc napompuj w onCreate, ale pokaż / ukryj w onPrepare.
JCutting8

89

Tak.

  1. Możesz ustawić flagę / warunek.
  2. Zadzwoń, invalidateOptionsMenu()gdy chcesz ukryć opcję. To zadzwonionCreateOptionsMenu() .
  3. W onCreateOptionsMenu()sprawdź flagę / warunek i pokaż lub ukryj ją w następujący sposób:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }

2
Nie powinno być invalidateOptionsMenuzamiast invalidateOptions?
razz

3
Jeśli ustawisz flagę na wartość logiczną, możesz po prostu ustawić widoczność elementu na flagę (lub! Flag), jeśli zajdzie taka potrzeba. Zatem item.setVisbility (! Flag); sprawia, że ​​jest to jedna podszewka bez warunku.
jwehrle

gdzie jest zdefiniowana zmienna „menu”?
Jonathan

Jest przekazywany jako parametr doonCreateOptionsMenu
suhas_sm

użycie tej metody oznacza, że ​​przedmiot nadal zajmuje miejsce i może pojawić się „przerwa” w interfejsie użytkownika w miejscu, w którym powinien znajdować się przycisk. Użycie removeItem w onPrepareOptionsMenu () załatwi sprawę.
JCutting8

39

Możesz to nazwać:

MenuItem item = menu.findItem(R.id.my_item);
item.setVisible(false);

Aktualizacja:

Upewnij się, że kod nie zwraca nullna itemlub może ulec awarii aplikacji.


użycie tej metody oznacza, że ​​przedmiot nadal zajmuje miejsce i może pojawić się „przerwa” w interfejsie użytkownika w miejscu, w którym powinien znajdować się przycisk. Użycie removeItem w onPrepareOptionsMenu () załatwi sprawę.
JCutting8

33

Szukałem odpowiedzi w nieco szerszym kontekście. Teraz, gdy to rozgryzłem, dodam tę odpowiedź.

Ukryj przycisk domyślnie w menu xml

Domyślnie przycisk udostępniania będzie ukryty, zgodnie z ustawieniem android:visible="false".

wprowadź opis zdjęcia tutaj

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- hide share button by default -->
    <item
        android:id="@+id/menu_action_share"
        android:icon="@drawable/ic_share_white_24dp"
        android:visible="false"     
        android:title="Share"
        app:showAsAction="always"/>

    <item
        android:id="@+id/menu_action_settings"
        android:icon="@drawable/ic_settings_white_24dp"
        android:title="Setting"
        app:showAsAction="ifRoom"/>

</menu>

Pokaż przycisk w kodzie

Ale przycisk udostępniania można opcjonalnie wyświetlić w zależności od pewnych warunków.

wprowadź opis zdjęcia tutaj

MainActivity.java

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.menu_action_share);

    // show the button when some condition is true
    if (someCondition) {        
        shareItem.setVisible(true);
    }

    return true;
}

Zobacz też

  • Konfigurowanie paska aplikacji (dokumenty systemu Android dotyczące pomocy przy konfigurowaniu paska aplikacji / działania)

OnPrepareOptionsMenu () powinien być używany do wyświetlania / ukrywania logiki zamiast onCreateOptionsMenu (), ponieważ jest wywoływany tylko raz, więc nie jest użyteczny, jeśli chcesz zmienić pozycje menu po jego inicjalizacji. Więc napompuj w onCreate, ale pokaż / ukryj w onPrepare, a następnie użyj, invalidateOptionsMenu()aby odświeżyć menu.
JCutting8

24

nie działało dla mnie. Musiałem wyraźnie użyć, onPrepareOptionsMenuaby ustawić element niewidoczny.

Więc użyj, onCreateOptionsMenuaby utworzyć menu i onPrepareOptionsMenuzmienić widoczność itp.


1
Dla mnie działało to w obie strony, ale w oparciu o dokumenty systemu Android onPrepareOptionsMenu wydaje się właściwym miejscem do wykonywania tego typu operacji: „Przygotuj standardowe menu opcji ekranu do wyświetlenia. Jest to wywoływane tuż przed wyświetleniem menu, za każdym razem, gdy jest wyświetlane. Możesz użyć tej metody, aby efektywnie włączać / wyłączać elementy lub w inny sposób dynamicznie modyfikować zawartość. ”
yuval

Tak, to jest idealne. Funkcja onPrepareOptionsMenu () powinna być używana do wyświetlania / ukrywania logiki zamiast funkcji onCreateOptionsMenu (), ponieważ jest wywoływana tylko raz, więc nie jest przydatna, jeśli chcesz zmienić pozycje menu po jej inicjalizacji. Więc napompuj w onCreate, ale pokaż / ukryj w onPrepare, a następnie użyj, invalidateOptionsMenu()aby odświeżyć menu.
JCutting8

9

Początkowo ustaw wartość widoczności elementu menu na wartość false w pliku układu menu w następujący sposób:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:visible="false"
        android:id="@+id/action_do_something"
        android:title="@string/txt_do_something"
        app:showAsAction="always|withText"
        android:icon="@drawable/ic_done"/>
</menu>

Następnie możesz po prostu ustawić widoczność elementu menu na wartość false w funkcji onCreateOptionsMenu () po napompowaniu menu.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(menu,R.menu.menu);
    MenuItem item = menu.findItem(R.id.menuItemId);
    if (item != null){
        item.setVisible(false);
    }
}

onCreateOptionsMenu nie zwraca wartości logicznej. Rozwiązanie działało jednak idealnie.
Joseph


7

To działało dla mnie zarówno z Aktywności, jak i Fragmentu

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    if (menu.findItem(R.id.action_messages) != null)
        menu.findItem(R.id.action_messages).setVisible(false);
}

1
W moim przypadku funkcja onPrepareOptionsMenu zwraca wartość logiczną, a nie nieważną.
CoolMind,

6

Odpowiedź P1r4nh4 działa dobrze, właśnie ją uprościłem, używając flagi boolean:

public int mState = 0; //at the top of the code
//where you want to trigger the hide action
mState = 1; // to hide or mState = 0; to show
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == 1) //1 is true, 0 is false
    {
        //hide only option 2
            menu.getItem(2).setVisible(false);
    }
}

2
Użycie 0i 1nie jest „flagą logiczną”, jest pseudo-logiczną. poza tym nie ma powodu, aby używać tutaj rzeczywistej wartości logicznej.
Ingo Bürk

2
Ponadto możesz mieć kilka stanów, nie tylko jeden do ukrycia i jeden do pokazania. W zależności od złożoności aplikacji i odmowy pisania nowych działań dla nowych stanów aplikacji, możesz mieć stan SHOW_ALL, HIDE_ALL, ale także HIDE_EDIT lub HIDE_SHARE na wypadek, gdybyś chciał ukryć pewne części swojego menu.
P1r4nh4,

4

Według oficjalnej strony Android Developer, OnCreateOptionMenu (menu Menu) nie jest zalecane do zmiany pozycji menu lub ikon, widoczności .. itp. W Runtime.

Po wywołaniu funkcji onCreateOptionsMenu () system zachowuje wystąpienie menu, które wypełniasz, i nie będzie ponownie wywoływał funkcji onCreateOptionsMenu (), chyba że menu zostanie z jakiegoś powodu unieważnione. Jednak należy użyć funkcji onCreateOptionsMenu () tylko do utworzenia początkowego stanu menu i nie wprowadzania zmian podczas cyklu życia działania.

Jeśli chcesz zmodyfikować menu opcji w oparciu o zdarzenia występujące podczas cyklu życia aktywności, możesz to zrobić w metodzie onPrepareOptionsMenu (). Ta metoda przekazuje ci obiekt Menu w takiej postaci, w jakiej aktualnie istnieje, abyś mógł go zmodyfikować, na przykład dodać, usunąć lub wyłączyć elementy. (Fragmenty zapewniają również wywołanie zwrotne onPrepareOptionsMenu ().) - Oficjalna strona AndroidDeveloper -

Zgodnie z zaleceniami Możesz użyć tej metody onOptionsItemSelected (pozycja MenuItem) do śledzenia danych wejściowych użytkownika.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.edit) {
        Intent intent = new Intent(this, ExampleActivity.class);
        intent.putExtra(BUNDLE_KEY, mConnection);
        startActivityForResult(intent, PICK_CHANGE_REQUEST);
        return true;
    } else if (id == R.id.delete) {
        showDialog(this);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

Jeśli chcesz zmienić pozycje menu w czasie wykonywania, możesz użyć onPrepareOptionsMenu (menu Menu), aby je zmienić

@Override
public boolean onPrepareOptionsMenu(Menu menu){

    if (Utils.checkNetworkStatus(ExampleActivity.this)) {
        menu.findItem(R.id.edit).setVisible(true);
        menu.findItem(R.id.delete).setVisible(true);
    }else {
        menu.findItem(R.id.edit).setVisible(false);
        menu.findItem(R.id.delete).setVisible(false);
    }
    return true;
} 

niektóre elementy są zawsze widoczne, więc gdy ja setVisible(false)dla zawsze widocznego elementu, nie znika, dopóki nie kliknę trzech kropek (samo menu). Jeśli użyję invalidateOptionsMenu()w onPrepareOptionsMenuprzedmiotach, natychmiast się reorganizuje, ale tracą one swoje działania (jeśli kliknę na dowolny element, nic nie robi).
Aliton Oliveira

3

ustaw wartość zmiennej i wywołaj invalidateOptionsMenu ();

na przykład

    selectedid=arg2;
            invalidateOptionsMenu();


 public boolean onPrepareOptionsMenu(Menu menu) {

    if(selectedid==1){
        menu.findItem(R.id.action_setting).setVisible(false);
        menu.findItem(R.id.action_s2).setVisible(false);
        menu.findItem(R.id.action_s3).setVisible(false);
    }
    else{
        if(selectedid==2){
            menu.findItem(R.id.action_search).setVisible(false);
            menu.findItem(R.id.action_s4).setVisible(false);
            menu.findItem(R.id.action_s5).setVisible(false);
        }
    }
    return super.onPrepareOptionsMenu(menu);
}

niektóre elementy są zawsze widoczne, więc gdy ja setVisible(false)dla zawsze widocznego elementu, nie znika, dopóki nie kliknę trzech kropek (samo menu). Jeśli użyję invalidateOptionsMenu()w onPrepareOptionsMenuprzedmiotach, natychmiast się reorganizuje, ale tracą one swoje działania (jeśli kliknę na dowolny element, nic nie robi).
Aliton Oliveira

3

Możesz użyć, toolbar.getMenu().clear();aby ukryć wszystkie elementy menu jednocześnie


@Ajeet_Yadav czy istnieje sposób, aby menu było widoczne po wyczyszczeniu?
Shawn

3

Po ustawieniu Widoczności wszystkich elementów w Menu, menu paska aplikacji lub menu przepełnienia będzie Ukrywać się automatycznie

Przykład

private Menu menu_change_language;

...

...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    ...
    menu_change_language = menu;
    menu_change_language.findItem(R.id.menu_change_language)
           .setVisible(true);

    return super.onCreateOptionsMenu(menu);
}

Przed przejściem do innego fragmentu użyj poniższego kodu:

if(menu_change_language != null){                 
    menu_change_language.findItem(R.id.menu_change_language)
       .setVisible(false);
}

2

https://stackoverflow.com/a/21215280/466363 - odpowiedzi: Look Alterno i Sufian

  • ActivityCompat.invalidateOptionsMenu () nie wywołuje wywołania zwrotnego onPrepareOptionsMenu (); po prostu aktualizuje menu bezpośrednio.
  • Moja someMethod () jest wywoływana z kilku miejsc, nawet przed onCreateOptionsMenu (), więc muszę sprawdzić mMenu! = Null.
  • powinien działać przy użyciu API 8

.

private Menu mMenu;
   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       inflater.inflate(R.menu.track_fragment, menu);
       mMenu = menu;
       }
   ...
   private void someMethod() {
   ...
       if (mMenu != null) {
          MenuItem item = mMenu.findItem(R.id.new_track);
          if (item != null) {
               item.setVisible(false);
               ActivityCompat.invalidateOptionsMenu(this.getActivity());
           }
       }
   ...
   }
  • ActivityCompat.invalidateOptionsMenu () nie wywołuje wywołania zwrotnego onPrepareOptionsMenu (); po prostu aktualizuje menu bezpośrednio.

  • Moja someMethod () jest wywoływana z kilku miejsc, nawet przed onCreateOptionsMenu (), więc muszę sprawdzić mMenu! = Null.

  • powinien działać przy użyciu API 8

2

Jeśli zrobiłeś wszystko jak w powyższych odpowiedziach, ale element menu jest nadal widoczny, sprawdź, czy odwołujesz się do unikalnego zasobu. Na przykład w onCreateOptionsMenu lub onPrepareOptionsMenu

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    MenuItem menuOpen = menu.findItem(R.id.menu_open);
    menuOpen.setVisible(false);
}

Ctrl + kliknij R.id.menu_open i sprawdź, czy istnieje tylko w jednym pliku menu. W przypadku, gdy ten zasób jest już gdziekolwiek używany i załadowany w działaniu, spróbuje się tam ukryć.


2

Najlepszym sposobem na ukrycie wszystkich pozycji w menu za pomocą jednego polecenia jest użycie „grupy” w menu xml. Po prostu dodaj wszystkie elementy menu, które będą w twoim menu przepełnienia w tej samej grupie.

W tym przykładzie mamy dwa elementy menu, które zawsze będą wyświetlane (zwykły element i wyszukiwanie) oraz trzy elementy przepełnienia:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/someItemNotToHide1"
        android:title="ITEM"
        app:showAsAction="always" />

    <item
        android:id="@+id/someItemNotToHide2"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="Search"/>

    <group android:id="@+id/overFlowItemsToHide">
    <item android:id="@+id/someID" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID2" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID3" 
    android:orderInCategory="1" app:showAsAction="never" />
    </group>
</menu>

Następnie, w swojej aktywności (najlepiej w onCreateOptionsMenu), użyj polecenia setGroupVisible, aby ustawić widoczność wszystkich pozycji menu na false lub true.

public boolean onCreateOptionsMenu(Menu menu) {
   menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible
}

Jeśli chcesz użyć tego polecenia w innym miejscu swojej aktywności, pamiętaj, aby zapisać klasę menu w lokalnym i zawsze sprawdź, czy menu jest puste, ponieważ możesz wykonać przed createOptionsMenu:

Menu menu;

public boolean onCreateOptionsMenu(Menu menu) {
       this.menu = menu;

}

public void hideMenus() {
       if (menu != null) menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible       
}


1

Myślę, że lepszym rozwiązaniem byłoby użycie zmiennej członka dla menu, zainicjowanie jej w onCreateOptionsMenu (), a następnie użycie setVisible () później, bez unieważniania menu opcji.


1

ten kod działał dla mnie

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu,menu);
    if (Application.sharedPreferences.getInt("type",1) == 2)
    {
        menuItem = menu.findItem(R.id.menu_travel_orders);
        menuItem.setVisible(false);
    }
    return super.onCreateOptionsMenu(menu);
}

1

To podejście zadziałało dla mnie:

private  Menu thismenu;

if (condition)
{
   if(thismenu != null)
   {
       thismenu.findItem(R.id.menu_save).setVisible(true);
       Toast.makeText(ProfileActivity.this, 
    ""+thismenu.findItem(R.id.menu_save).getTitle(),
                Toast.LENGTH_SHORT).show();
   }else
   {
       thismenu.findItem(R.id.menu_save).setVisible(false);
   }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getMenuInflater().inflate(R.menu.profile_menu, menu);
   thismenu = menu;

   return true;
}

1

Próbujesz uzyskać dostęp do elementu menu z działania, które nie ma dostępu do zakresu. Wywołanie znalezienia elementu menu zwróci null , ponieważ widok nie jest powiązany ani z działaniem, ani z układem którego dzwonisz.

Elementy menu są powiązane z elementami takimi jak „ Pasek nawigacji ”, które z kolei są powiązane z odpowiednią aktywnością.

Więc zainicjuj te widoki w activity (), a następnie uzyskaj dostęp do elementów menu za pomocą tych widoków.

Navigation navView;
navView = findViewById(R.id.navigationView);

MenuItem item = navView.getMenu().findItem(R.id.item_hosting);
item.setVisible(false);

1

posługiwać się invalidateOptionsMenu()

aby zadzwonić onPrepareOptionsMenu(menu: Menu?)

powinieneś używać onCreateOptionsMenu () tylko do utworzenia początkowego stanu menu i nie wprowadzać zmian podczas cyklu życia aktywności ...

Gdy wystąpi zdarzenie i chcesz przeprowadzić aktualizację menu, musisz wywołać invalidateOptionsMenu (), aby zażądać wywołania systemowego onPrepareOptionsMenu ().

https://developer.android.com/guide/topics/ui/menus


0

Android kotlin, ukryj lub ustaw programowo widoczność pozycji menu na pasku akcji.

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater = menuInflater
    inflater.inflate(R.menu.main_menu, menu)
    val method = menu.findItem(R.id.menu_method)
    method.isVisible = false //if want to show set true
    return super.onCreateOptionsMenu(menu)
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.