it-swarm.com.de

Wie kann ich die ActionBar aktualisieren, wenn die Menüeinträge von onPrepareOptionsMenu gewechselt wurden?

In meinen Apps aktiviere/deaktiviere ich oft Menüeinträge und mache sie im onPrepareOptionsMenu sichtbar.

Heute habe ich begonnen, das Android-Attribut "showAsAction" zu einigen meiner Android 2.x-Apps hinzuzufügen, um Menüeinträge anzuzeigen, die in der ActionBar am häufigsten verwendet werden.

Die ActionBar spiegelt nicht sofort die Aktivierung/Deaktivierung und Sichtbarkeit wider. Ich muss auf das Menü auf der rechten Seite klicken, um diese Änderung zu sehen.

Ok, ich verstehe, dass das Menü onPrepareOptionsMenu ausgelöst wird. Aber was muss ich tun, um die ActionBar aufzufrischen? Ich denke, diese Änderung muss innerhalb von onOptionsItemSelected angewendet werden, aber ich weiß nicht, was ich anrufen soll.

Hier ist das Menü:

<item
    Android:icon="@drawable/ic_menu_mapmode"
    Android:id="@+id/men_mapview"
    Android:showAsAction="ifRoom|withText"
    Android:title="@string/txt_mapview" />

<item
    Android:icon="@drawable/ic_menu_mapmode"
    Android:id="@+id/men_satelliteview"
    Android:showAsAction="ifRoom|withText"
    Android:title="@string/txt_satelliteview" />

Hier ist das onPrepareOptionsMenu:

@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
    MenuItem menuItemMapView = menu.findItem(R.id.men_mapview);
    MenuItem menuItemSatelliteView = menu.findItem(R.id.men_satelliteview);

    if (mapView.isSatellite()) {
        menuItemMapView.setEnabled(true).setVisible(true);
        menuItemmenuItemSatelliteView.setEnabled(false).setVisible(false);
    } else {
        menuItemMapView.setEnabled(false).setVisible(false);
        menuItemmenuItemSatelliteView.setEnabled(true).setVisible(true);
    }

    return super.onPrepareOptionsMenu(menu);
}

Hier ist das onOptionsItemSelected

@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
    switch (menuItem.getItemId()) {
        case R.id.men_mapview:
            mapView.setSatellite(false);
            mapView.setStreetView(true);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
        case R.id.men_satelliteview:
            mapView.setSatellite(true);
            mapView.setStreetView(false);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
    }

    return super.onOptionsItemSelected(menuItem);
}

BEARBEITEN: Wenn ich invalidateOptionsMenu hinzufüge, funktioniert dies bei Android 3.x-Apps, stürzt jedoch bei Android 2.x-Geräten aufgrund einer fehlenden Methode ab. Was ist der empfohlene Weg, um es richtig zu machen?

56
Harald Wilhelm

Meine Methode der Wahl ist das Erstellen einer Hilfsklasse. Zum Beispiel:

class VersionHelper
{
    static void refreshActionBarMenu(Activity activity)
    {
        activity.invalidateOptionsMenu();
    }
}

Ersetzen Sie jetzt in Ihrem Code oben invalidateOptionsMenu(); durch:

if (Build.VERSION.SDK_INT >= 11)
{
    VersionHelper.refreshActionBarMenu(this);
}

Diese Methode geht an CommonsWare (suchen Sie nach HoneycombHelper und überprüfen Sie seine Bücher - sehr zu empfehlen)

81
wirbly

Dank der akzeptierten Antwort. Ich verwende ActionBarActivity. In dieser Klasse können Sie verwenden 

supportInvalidateOptionsMenu();
66

Benutzen

ActivityCompat.invalidateOptionsMenu(Activity activity)

aus der kompatiblen Bibliothek .

Siehe: https://stackoverflow.com/a/14748687/435855

14
Urizev

einen Verweis auf das Menü speichern und anrufen:

this.menu.clear();
this.onCreateOptionsMenu(this.menu);
10
Klaasvaak

Sie können jetzt die supportInvalidateOptionsMenu () - Methode aus der ActionbarActivity mit der Support-Bibliothek verwenden. Sie müssen also nicht nach der Version der SDK suchen. Geht bis API 7 und höher.

http://developer.Android.com/reference/Android/support/v7/app/ActionBarActivity.html

dazu müssen Sie die v7 der Support Library mit diesem importieren

http://developer.Android.com/tools/support-library/setup.html

4
Farfelufrank

Basierend auf "Klaasvaak" Antwort oben. Ich benutze seinen SubMenus. Das funktioniert für mich:

// Declare and save the menu as global, so it can be called anywhere.
Menu absTopSubMenus;

public boolean onCreateOptionsMenu(Menu menu) {

absTopSubMenus = menu;  // Used for re-drawing this menu anywhere in the codes.

// The remainder of your code below
}

Um dies erneut zu zeichnen, rufen Sie einfach an:

// Redraw the top sub-menu
absTopSubMenus.clear();
onCreateOptionsMenu(absTopSubMenus);
3
Britc

Ich bin nicht sicher, ob Sie es bereits gesehen haben, aber wenn Sie die actionbar ausgiebig verwenden und planen, niedrigere APIs (> 8) zu unterstützen, werfen Sie einen Blick auf die actionBarSherlock-Bibliothek. Dies macht es so, dass Sie Ihren actionBar-Code nicht für niedrigere und höhere APIs einteilen müssen. Dann können Sie einfach Folgendes ausführen:

runOnUiThread(new Runnable(){
  @Override
  public void run(){
    supportInvalidateOptionsMenu();
  }
});
3
user1528493

getActivity (). invalidateOptionsMenu ();

erledigt die Arbeit.

2
Karun Shrestha

Ein dickes Lob an @Klaasvaak für den Weg hierher. Ich verwende Folgendes, das sowohl vor als auch nach API 11 funktioniert:

private void invalidOptionsMenuHelper() {
    if (Build.VERSION.SDK_INT >= 11) {
        invalidateOptionsMenu();

    } else if (mOptionsMenu != null) {
        mOptionsMenu.clear();
        onCreateOptionsMenu(mOptionsMenu);
    }
}

Natürlich müssen Sie einen Verweis auf das Menü (in diesem Fall mOptionsMenu) speichern, das ich über Folgendes erzeuge:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    mOptionsMenu = menu;

    //... create and manage the menu normally
}
1
Mike Repass

Stellen Sie außerdem sicher, dass Sie nicht anrufen 

myAppCompatActivity.setToolbarTitle("some dynamic title");

kurz nachdem Sie Ihr Menü aktualisiert haben. 

Ich hatte das Problem, dass die Drawables nicht auftauchen würden, selbst wenn es Platz für sie gibt. Nachdem ich eine Orientierungsänderung vorgenommen hatte, erschienen die Drawables dann ..?

In Summe:

Hauptaktivität:

public class MainActivity extends AppCompatActivity {

    private boolean showMenu = true;

    public void setShowMenu(boolean show) {
        showMenu = show;
        supportInvalidateOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.my_menu, menu);
        menu.findItem(R.id.menu_share).setVisible(showMenu);
        // menu.findItem(...
        return true;
    }
}

FragmentNoMenu:

public abstract class FragmentNoMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(false);
        }
    }

}

FragmentWithMenu:

public abstract class FragmentWithMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(true);
        }
    }

}
0
IHeartAndroid