Android: Wie aktiviere / deaktiviere ich den Optionsmenüpunkt beim Klicken auf die Schaltfläche?


127

Ich kann es leicht tun, wenn ich onCreateOptionsMenuoder onOptionsItemSelectedMethoden verwende.

Aber ich habe irgendwo auf dem Bildschirm eine Schaltfläche, und wenn ich auf diese Schaltfläche klicke, sollte sie Kontextmenüelemente aktivieren / deaktivieren.

Antworten:


272

Wie auch immer, die Dokumentation deckt alle Dinge ab.

Ändern von Menüelementen zur Laufzeit

Sobald die Aktivität erstellt wurde, wird die onCreateOptionsMenu()Methode wie oben beschrieben nur einmal aufgerufen. Das System behält Menudie in dieser Methode definierten Daten bei und verwendet sie wieder , bis Ihre Aktivität zerstört ist. Wenn Sie das Optionsmenü jederzeit nach seiner ersten Erstellung ändern möchten, müssen Sie die onPrepareOptionsMenu()Methode überschreiben . Dadurch erhalten Sie das Menüobjekt, wie es derzeit vorhanden ist. Dies ist nützlich, wenn Sie Menüelemente je nach aktuellem Status Ihrer Anwendung entfernen, hinzufügen, deaktivieren oder aktivieren möchten.

Z.B

@Override
public boolean onPrepareOptionsMenu (Menu menu) {
    if (isFinalized) {
        menu.getItem(1).setEnabled(false);
        // You can also use something like:
        // menu.findItem(R.id.example_foobar).setEnabled(false);
    }
    return true;
}

Unter Android 3.0 und höher gilt das Optionsmenü immer als geöffnet, wenn Menüelemente in der Aktionsleiste angezeigt werden. Wenn ein Ereignis auftritt und Sie eine Menüaktualisierung durchführen möchten, müssen Sie anrufen invalidateOptionsMenu(), um den Systemaufruf anzufordern onPrepareOptionsMenu().


2
setEnable()ändert sich, was passiert, wenn Sie dieses Menü drücken, ändert aber nicht, wie es aussieht (was ist los, Android-Entwickler?). Es ist also klarer, entweder den Titel zu deaktivieren und zu ändern oder vorzugsweise nur das MenuItemUnsichtbare zu machen.
Vlad

19
Schneller Tipp: falseKehren Sie zurück , um das Menü vollständig zu deaktivieren.
Bart Friederichs

5
Außerdem heißt es im API-Kommentar zu onPrepareOptionsMenu eindeutig: Das Ableiten von Klassen sollte immer (!) Die Basisklassenimplementierung aufrufen. Du hast deinen Superanruf dort vergessen.
AgentKnopf


Woher kennen Sie die zur Laufzeit hinzugefügte Ganzzahl-ID von MenuItem? Sie können sie nur nach Namen hinzufügen.
Antonio Sesto

66

Bei allen Android-Versionen ist dies am einfachsten: Verwenden Sie diese Option, um ein Menüaktionssymbol als deaktiviert anzuzeigen und es auch als deaktiviert zu aktivieren:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

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

    if (myItemShouldBeEnabled) {
        item.setEnabled(true);
        item.getIcon().setAlpha(255);
    } else {
        // disabled
        item.setEnabled(false);
        item.getIcon().setAlpha(130);
    }
}

1
Warum Alpha auf 0 setzen, wenn Sie die Sichtbarkeit auf false setzen können?
MLProgrammer-CiM

8
Ich setze Alpha nicht auf 0, sondern auf 130.
Frank

8
Hängt vom Kontext der Schaltfläche ab. Wenn die Funktion, die die Schaltfläche normalerweise bietet, im aktuellen Status völlig unbrauchbar ist, sollte die Sichtbarkeit unsichtbar / verschwunden sein. Wenn die Funktion, für die die Schaltfläche normalerweise verwendet wird, aus welchen Gründen auch immer verwendet werden KÖNNTE (z. B. wenn der Benutzer ein Premium-Mitglied wird, wenn sich der Benutzer anmeldet, wenn der Benutzer eine Verbindung zum Internet herstellt usw.), ist es schön, wenn sie ausgegraut ist weil dann der Benutzer weiß, dass eine Funktion vorhanden ist, auf die er aus irgendeinem Grund keinen Zugriff hat.
Yiati

6
Das Setzen des Symbols auf unsichtbar ist in fast allen Anwendungsfällen nicht besser. Wenn Sie eine Gruppe haben, ist es besser, wenn diese an ihren Positionen bleibt und ausgegraut dem Benutzer anzeigt, dass es eine Option gibt, die in einem bestimmten Programmstatus aktiviert werden kann. Es ist sehr dumm, Dinge unsichtbar und unsichtbar zu machen und wahrscheinlich Layoutänderungen zu verursachen. Es gibt einen Grund, warum die meisten Menüs Elemente ausgegraut und je nach Modus nicht entfernt haben.
RichieHH

1
Wie, wenn das Menü kein Symbol enthält? Sie können Alpha () nicht setzen.
Latief Anwar

42

Sie können das Element beim Erstellen des Optionsmenüs als Variable speichern und dann seine Eigenschaften nach Belieben ändern.

private MenuItem securedConnection;
private MenuItem insecuredConnection;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.connect_menu, menu);
    securedConnection = menu.getItem(0);
    insecuredConnection =  menu.getItem(1);
    return true;
}

public void foo(){
       securedConnection.setEnabled(true);
}    

Das ist die richtige Antwort auf jede Android-Version. Die validierte Antwort gilt nur für API 11> -Geräte.
Marco HC

2
Ich habe es versucht und es funktioniert nicht. Meinten Sie onPrepareOptionsMenu?
Christopher Pickslay

6

Vereinfachen Sie die @ Vikas-Version

@Override
public boolean onPrepareOptionsMenu (Menu menu) {

    menu.findItem(R.id.example_foobar).setEnabled(isFinalized);
    return true;
}

4

So aktualisieren Sie das aktuelle Menü, um die Elemente zu aktivieren oder zu deaktivieren, wenn eine AsyncTask abgeschlossen ist.

In meinem Anwendungsfall musste ich mein Menü deaktivieren, während meine AsyncTask Daten lud. Nachdem ich alle Daten geladen hatte, musste ich das gesamte Menü erneut aktivieren, damit der Benutzer es verwenden konnte.

Dadurch wurde verhindert, dass Benutzer beim Laden von Daten auf Menüelemente klicken konnten.

Zuerst deklariere ich eine Zustandsvariable. Wenn die Variable 0 ist, wird das Menü angezeigt. Wenn diese Variable 1 ist, wird das Menü ausgeblendet.

private mMenuState = 1; //I initialize it on 1 since I need all elements to be hidden when my activity starts loading.

Dann suche onCreateOptionsMenu()ich in meiner nach dieser Variablen. Wenn es 1 ist, deaktiviere ich alle meine Elemente. Wenn nicht, zeige ich sie einfach alle an

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_galeria_pictos, menu);

        if(mMenuState==1){
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(false);
            }
        }else{
             for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(true);
            }
        }

        return super.onCreateOptionsMenu(menu);
    }

Nun, wenn meine Aktivität beginnt, onCreateOptionsMenu() wird sie nur einmal aufgerufen, und alle meine Gegenstände sind verschwunden, weil ich zu Beginn den Status für sie eingerichtet habe.

Dann erstelle ich eine AsyncTask, in der ich diese Statusvariable in meinem auf 0 setze onPostExecute()

Dieser Schritt ist sehr wichtig!

Wenn du anrufst invalidateOptionsMenu(); , wird es neu gestartetonCreateOptionsMenu();

Nachdem ich meinen Status auf 0 gesetzt habe, zeichne ich einfach das gesamte Menü neu, aber diesmal mit meiner Variablen auf 0, das heißt, das gesamte Menü wird angezeigt, nachdem der gesamte asynchrone Prozess abgeschlossen ist, und dann kann mein Benutzer das Menü verwenden .

 public class LoadMyGroups extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMenuState = 1; //you can set here the state of the menu too if you dont want to initialize it at global declaration. 

        }

        @Override
        protected Void doInBackground(Void... voids) {
           //Background work

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            mMenuState=0; //We change the state and relaunch onCreateOptionsMenu
            invalidateOptionsMenu(); //Relaunch onCreateOptionsMenu

        }
    }

Ergebnisse

Geben Sie hier die Bildbeschreibung ein


2

Die beste Lösung, wenn Sie mit der Navigationsschublade arbeiten

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.setGroupVisible(0,false);
        return true;
    }

Dies verbirgt das gesamte Menü und macht es unmöglich, es wieder zu öffnen
MrStahlfelge

2

Eine modernere Antwort auf eine alte Frage:

MainActivity.kt

private var myMenuIconEnabled by Delegates.observable(true) { _, old, new ->
    if (new != old) invalidateOptionsMenu()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    findViewById<Button>(R.id.my_button).setOnClickListener { myMenuIconEnabled = false }
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_main_activity, menu)
    return super.onCreateOptionsMenu(menu)
}

override fun onPrepareOptionsMenu(menu: Menu): Boolean {
    menu.findItem(R.id.action_my_action).isEnabled = myMenuIconEnabled
    return super.onPrepareOptionsMenu(menu)
}

menu_main_activity.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">
<item
    android:id="@+id/action_my_action"
    android:icon="@drawable/ic_my_icon_24dp"
    app:iconTint="@drawable/menu_item_icon_selector"
    android:title="My title"
    app:showAsAction="always" />
</menu>

menu_item_icon_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?enabledMenuIconColor" android:state_enabled="true" />
<item android:color="?disabledMenuIconColor" />

attrs.xml

<resources>   
    <attr name="enabledMenuIconColor" format="reference|color"/>
    <attr name="disabledMenuIconColor" format="reference|color"/>
</resources>

styles.xml or themes.xml

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="disabledMenuIconColor">@color/white_30_alpha</item>
    <item name="enabledMenuIconColor">@android:color/white</item>

Großartiger Ansatz, der ohne viel Boilerplate rund um die App verwendet werden kann.
Arthur

Welches Problem hast du?
ExpensiveBelly

@ExpensiveBelly kein Problem an sich, nur öffentliche Bekanntmachung.
Big McLargeHuge

1
  @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

                case R.id.item_id:

                       //Your Code....

                        item.setEnabled(false);
                        break;
              }
            return super.onOptionsItemSelected(item);
     }

Aus der Bewertung: Hallo, bitte antworten Sie nicht nur mit dem Quellcode. Versuchen Sie, eine schöne Beschreibung der Funktionsweise Ihrer Lösung zu geben. Siehe: Wie schreibe ich eine gute Antwort? . Danke
sɐunıɔ ןɐ qɐp

1

Was ich getan habe, war einen Verweis auf das Menü unter zu speichern onCreateOptionsMenu. Dies ähnelt der Antwort von nir, außer dass ich nicht jedes einzelne Element, sondern das gesamte Menü gespeichert habe.

Deklarieren Sie ein Menü Menu toolbarMenu;.

Dann onCreateOptionsMenuspeichern Sie im Menü auf Ihre Variable

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    getMenuInflater().inflate(R.menu.main_menu, menu);
    toolbarMenu = menu;
    return true;
}

Jetzt können Sie jederzeit auf Ihr Menü und alle Elemente zugreifen. toolbarMenu.getItem(0).setEnabled(false);


0
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    // getMenuInflater().inflate(R.menu.home, menu);
    return false;
}

2
Während dieser Code möglicherweise die Frage des OP beantwortet, helfen ein paar erklärende Worte aktuellen und zukünftigen Benutzern, Ihre Antwort noch besser zu verstehen.
Thom

0

Wenn sichtbar Menü

menu.findItem(R.id.id_name).setVisible(true);

Wenn Menü ausblenden

menu.findItem(R.id.id_name).setVisible(false);

-4

Im Allgemeinen können die Eigenschaften Ihrer Ansichten zur Laufzeit geändert werden:

(Button) item = (Button) findViewById(R.id.idBut);

und dann...

item.setVisibility(false)

aber

Wenn Sie die Sichtbarkeit der Optionen im ContextMenu ändern möchten, können Sie beim Drücken Ihrer Taste ein Flag aktivieren und dann im onCreateContextMenu Folgendes tun:

 @Override
        public void onCreateContextMenu(ContextMenu menu, 
                View v,ContextMenu.ContextMenuInfo menuInfo) {

            super.onCreateContextMenu(menu, v, menuInfo);

                menu.setHeaderTitle(R.string.context_title);

                if (flagIsOn()) {
                    addMenuItem(menu, "Option available", true);
                } else {
                    Toast.makeText(this, "Option not available", 500).show();
                }

        }

ich hoffe das hilft


Ich muss sagen, dass Sie sich irren. Ich möchte, dass der Menüpunkt deaktiviert wird, nicht die Schaltfläche.
Vikas

Meine Antwort ist abgeschlossen. Dieser Code funktioniert, ich habe in meinen Projekten verwendet
Eric

1
Nun, danke für die Arbeit, aber Sie sollten die Frage richtig lesen, dass ich bereits angegeben habe, dass ich sie in der onCreateContextMenuMethode ändern kann . Ich möchte jedoch außerhalb dieser Methode auf das Kontextmenü zugreifen.
Vikas

onCreateContextMenuwird nur einmal aufgerufen, aber ich kann viel Zeit auf die Schaltfläche klicken, um den Menüpunkt zu aktivieren / deaktivieren.
Vikas

Ja, aber das Kontextmenü wird normalerweise ausgeblendet. Wenn Sie die Taste "Irgendwo" drücken und das Flag wie gesagt setzen, ist dieses Kontextmenü nicht sichtbar. Wenn Sie das nächste Mal Ihr Kontextmenü neu laden, ist diese Option unsichtbar. Eine andere Möglichkeit besteht darin, eine andere Art von Menü mit demselben Erscheinungsbild zu erstellen, um die Ereignisse mit anderen Methoden zu behandeln.
Eric
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.