Optionsmenu funktioniert nicht richtig

  • Antworten:14
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 43

09.01.2017 19:54:44 via Website

Hallo,

ich habe ein Problem mit meinem Optionsmenu und hoffe das mir vielleicht jemand helfen kann.
In der ActionBar habe ich zwei Menüs. Das eine ist einfach nur ein einziges Icon (online/offline), das andere ist ein Einstellungs-Menü mit 3 Einträgen welche sich beim drücken auf die 3 Punkte oben rechts öffnet. Wenn ich jedoch die Einträge aus dem Menü auswähle, so wird die onOptionsItemSelected(MenuItem item) Methode nur manchmal aufgerufen. Das heißt: Manchmal muss ich 3 mal auf den Eintrag drücken bis die Methode aufgerufen wird. Nur manchmal klappt es schon beim ersten mal und manchmal muss ich zwei mal drücken. Ein wirkliches Muster wann 1x reicht und wann zwei oder drei mal gedrückt werden muss konnte ich nicht feststellen. Interessanter weise: Die kleine "Animation", dass der Menüeintrag beim drücken kurz dunkel Hinterlegt wird, kommt immer (egal ob die onOptionsItemSelected Methode aufgerufen wird oder nicht). Das Menü bleibt im Fehlerfall einfach offen. Ich drücke dann eben mehrfach auf den Eintrag bis die onOptionsItemSelected Methode aufgerufen wird und sich das Menü nach dessen Ausführung auch wieder schließt.

Meine MainActivity (die wichtigsten Stellen):

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

    appElements.menu = menu;

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.v("info", "item selected");

    int id = item.getItemId();

    if (id == R.id.action_settings) {
        startActivity(new Intent(this, SettingsActivity.class));
    }
    return true;

}

Die action_bar_items.xml:

<?xml version="1.0" encoding="utf-8"?>

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">

<!-- "Mark Favorite", should appear as action button if possible -->
<item
    android:id="@+id/action_connection"
    android:icon="@drawable/offline"
    android:title="Connect"
    app:showAsAction="ifRoom"/>

Und die settings_menu_items.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
    android:id="@+id/action_settings"
    android:orderInCategory="100"
    android:title="Einstellungen"
    app:showAsAction="never" />
<item
    android:id="@+id/action_login"
    android:orderInCategory="100"
    android:title="Login"
    app:showAsAction="never" />
<item
    android:id="@+id/action_refresh"
    android:orderInCategory="100"
    android:title="Refresh"
    app:showAsAction="never" />

  • Forum-Beiträge: 8

11.01.2017 13:15:37 via Website

Hi, möglicherweise laufen zu viele Prozesse im Hintergrund so dass die Anwendung hängenbleibt (?)

  • Forum-Beiträge: 2.211

11.01.2017 13:19:29 via Website

Hallo Enrico,

hau dir doch mal anstatt des Activity-Calls ein Log rein und schau mal, ob es dann auch
auch hängt.

 if (id == R.id.action_settings) {
    Log.d (TAG," Call of Settings");
}

Wenn nicht, dann hat deine Setup-Activity ein Lag.

— geändert am 11.01.2017 13:20:44

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 43

11.01.2017 16:56:28 via Website

Hallo,

also ich habe ja bereits den

Log.v("info", "item selected");

in der onOptionsItemSelected stehen und sehe, dass in den Fällen in denen er auf den klick nicht reagiert auch dieser Logeintrag nicht kommt. Nur in den Fällen wo das drauf drücken funktioniert, kommt auch der Logeintrag. Das macht mich so sicher, dass die onOptionsItemSelected eben öfters gar nicht erst aufgerufen wird. Die Frage ist nur woran das liegt.

  • Forum-Beiträge: 2.211

11.01.2017 17:08:34 via Website

Da solltest du dir gar nicht sicher sein .

Es kann durchaus sein , dass das System nicht frei läuft .
(Ich habe mir schon was dabei gedacht , als ich dir das oben geschrieben habe)

Klammer es doch einfach mal aus und schau dann mal

b)

warum haust du zwei xmls hintereinander rein ??

getMenuInflater().inflate(R.menu.action_bar_items, menu);
getMenuInflater().inflate(R.menu.settings_menu_items, menu);

Damit überschreibst du das Erste

— geändert am 11.01.2017 17:18:53

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 43

11.01.2017 19:38:07 via Website

Klammer es doch einfach mal aus und schau dann mal

Was soll ich ausklammern? Wie gesagt, den Logeintrag habe ich ja in der onOptionsItemSelected drin.

warum haust du zwei xmls hintereinander rein ??

Das liegt daran das ich zwei Menüs in der Actionbar haben möchte.
Zum einen die action_bar_items, was mir ein anklickbares Icon darstellt welches ich als online/offline Anzeige verwende.
die settings_menu_items werden in der Actionbar als 3 Punkte angezeigt, wenn man drauf drückt öffnet sich das submenü mit den Einträgen Einstellungen, Login, Refresh (siehe settings_menu_items.xml)

Ich habe auch testweise schon mal die action_bar_items weg gelassen, sodass ich nur ein einziges Menü (Das settings-menu) in der ActionBar habe. Doch das Problem bliebt das gleiche.

PS: getMenuInflater().inflate(...) fügt einen neuen Eintrag zum Menü hinzu. Die vorherigen werden dabei nicht überschrieben.
Vielleicht mache ich aber eben auch genau an dem Punkt irgendwas falsch.

  • Forum-Beiträge: 2.211

11.01.2017 20:22:59 via Website

Hmm wir drehen uns im Kreis

Was soll ich ausklammern?

Ich habe dir oben erklärt , warum du NUR den Intent mal weglassen sollst.
Ich bin ein wenig verwundert , warum du lieber diskutierst, anstatt das einfach mal die 20 Sekunden zu tun :-)

Möchtest Du nun Hilfe aus der Ferne , oder nicht ?
Wir sitzen hier und versuchen dir zu helfen , haben weder deine Entwicklungsumgebung, noch dein Projekt vor uns und müssen aus der Ferne unsere Kristallkugel anwerfen. Noch haben wir einen ErrorLog deinerseits.

Vielleicht mache ich aber eben auch genau an dem Punkt irgendwas falsch.

Du kannst nicht einfach zwei Inflates hintereinander ausführen und hoffen, dass sie zusammengebastelt werden .

— geändert am 11.01.2017 20:24:49

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 43

11.01.2017 20:32:30 via Website

Okay, da stand ich etwas auf dem Schlauch. Tut mir leid.

Ich habe nun mal alle Intents aus der onOptionsItemSelected auskommentiert. Sodass in der onOptionsItemSelected im grunde gar nichts mehr gemacht wird. Das Ergebnis blieb das gleiche.

Du kannst nicht einfach zwei Inflates hintereinander ausführen und hoffen, dass sie zusammengebastelt werden .

Okay, dann liegt vielleicht genau da der Fehler.
Wie wäre denn der richtige Weg zwei Menüs in die ActionBar zu implementieren. Also so dass man zwei Icons in der Leiste hat und beim drauf drücken sich das jeweilige Menü öffnet?

  • Forum-Beiträge: 2.211

11.01.2017 20:42:25 via Website

Es hängt ganz stark vom verwendeten SDK ab - am einfachsten macht man es so in der Richtung
(Nicht getestet)

menu.xml

< ?xml version="1.0" encoding="utf-8"? >
< menu xmlns:android="http://schemas.android.com/apk/res/android" >
< item android:id="@+id/next"
android:icon="@drawable/ic_next"
android:title="@string/next" />
< item android:id="@+id/previous"
android:icon="@drawable/ic_previous"
android:title="@string/previous" />
< item android:id="@+id/list"
android:icon="@drawable/ic_list"
android:title="@string/list" />
< /menu >

Dann

public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}

und

public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.next:
Toast.makeText(this, "You have clicked the " + getResources().getString(R.string.next) + " menu option",
Toast.LENGTH_SHORT).show();
return true;

default:
return super.onOptionsItemSelected(item);
}
}

— geändert am 11.01.2017 20:47:46

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 43

11.01.2017 21:13:22 via Website

Ich verwende Android Studio.

Dein Beispiel habe ich mal eingegeben. Das Menü reagiert damit auf jeden Klick (beim ersten mal, so wie es sein soll).
Die Frage ist nun aber, wie ich noch ein zweites Menü hinzufügen kann.

Vielleicht zum Verständnis zwei Bilder:

Mit deinem Beispiel sieht die ActionBar so aus:
image

Drückt man auf die 3 Punkte, klappt sich das Menü mit den 3 Unterpunkten aus.

In meiner App möchte ich nun links neben diesem Menü noch ein Icon haben. Das sieht bei mir momentan so aus:
image
Dieses Icon wechselt einfach zwischen rot und grün wenn man drauf drückt.

Umgesetzt, wie oben beschrieben (mit dem doppelten Aufruf von getMenuInflater().inflate(....)
Nur eben mit dem Nachteil, das es nicht sauber funktioniert.

Was wäre denn der Korrekte Weg in deinem Beispiel nun noch das zweite Menü bzw. Icon in die ActionBar hinzuzufügen?

  • Forum-Beiträge: 2.211

11.01.2017 21:18:03 via Website

Na siehste, jetzt kommen wir Stück für Stück weiter :-)

Du machst grundsätzlich einen Gedankenfehler.

Das was du machen willst, geht schlichtweg nicht über das Menu , sondern über die ActionBar.

Die standard Actionbar verfügt nur über ein Menu, das was du aber haben willst , ist
ein "Custom Actionbar" - das heisst , du musst dir erst mal eine eigene Actionbar basteln , damit du zwei Menus/Icons
unterbringen kannst.

Hier mal ein Beispiel :

https://guides.codepath.com/android/Extended-ActionBar-Guide

— geändert am 11.01.2017 21:21:20

Liebe Grüße - Stefan
[ App - Entwicklung ]

Ludy
  • Mod
  • Blogger
  • Forum-Beiträge: 6.770

11.01.2017 21:28:29 via Website

Hallo zusammen,

die beiden XML's zusammenfassen und bei dem anzuzeigenden Icon

    app:showAsAction="always"

einfügen. Den Import hier nicht vergessen:

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

Gruß Ludy (App Entwickler)

Mein Beitrag hat dir geholfen? Lass doch ein "Danke" da.☺

Lebensmittelwarnung App-Thread

Download Samsung Firmware Tool

  • Forum-Beiträge: 43

12.01.2017 06:12:49 via Website

Hallo,

vielen Dank für die Inputs.
In der Tat zeigt sich, das ich einfach zu doof war die Doku richtig zu lesen. Ich habe nun alle Items in ein Menü gemacht und showAsAction="always" gesetzt, wie es Ludy geschrieben hat. Dadurch muss ich nur noch 1 Menu inflaten. Und erhalte von der Darstellung her genau das was ich haben möchte.
Das Problem, dass die Klicks im Menü oft nicht erkannt wurden blieb aber bestehen.

Da es nun alles in einem Menü ist, bin ich der Sache auf die Schliche gekommen. Der rote Punkt wird ja unter bestimmen bedingungen grün oder rot angezeigt. Das habe ich so gelöst:

protected void onDraw(Canvas c)
{
    if(menu != null) {
        if(con.isConnected())
            menu.getItem(0).setIcon(getResources().getDrawable(R.drawable.online));
        else
            menu.getItem(0).setIcon(getResources().getDrawable(R.drawable.offline));
    }
}

Und genau hier scheint das Problem zu liegen, denn wenn ich diesen codeabschnitt auskommentiere, funktioniert das Menü auch immer beim ersten Klick, wie es sein soll.
Anscheinend gibt es Probleme wenn setIcon(...) in einem ungünstigen Zeitpunkt zum klick-Event kommt.
Ich habe es nun zumindest soweit eingeschränkt, dass das Icon tatsächlich nur dann geändert wird, wenn es auch nötig ist, nicht wie bisher bei jedem onDraw-Aufruf.
Das scheint das Problem nun behoben zu haben. Bzw. hat es eigentlich nur die Auftrittswahrscheinlichkeit deutlich verringert, da das Icon ja nicht so oft verändert wird (nur beim online-gehen, offline-gehen und wenn die Verbindung unterbrochen wird).
Vielleicht gibt es auch noch einen sauberen Weg das Icon während der Laufzeit zu verändern, ohne dass das Menü die Klicks verschluckt?

  • Forum-Beiträge: 2.211

12.01.2017 06:29:10 via Website

Hallo Enrico,

du musst aber zugeben , dass du die Routine , die dein Icon in der ActionBar setzt , uns bis eben vorenthalten hast.
Es wäre schön gewesen , wenn wir das von Anfang an gewusst hätten.
Wir können dann nicht effektiv arbeiten und auch helfen , sondern stochern noch mehr in der Kristallkugel herum.

Nun, da ich jetzt deinen Code nicht ganz kenne , würde ich diese Routine zum setzen des Icons in einen Thread implementieren ( z.b. AsyncTask) und/oder eine runOnUIThread Routine zu verwenden.

Ich denke dann kommst du alleine zurecht.

— geändert am 12.01.2017 10:50:49

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 43

12.01.2017 17:34:21 via Website

Vielen Dank für die Hilfe!
Ihr habt mir sehr weitergeholfen.

PS: Ich will hier natürlich keine 1000 Zeilen Code hochladen und versuche deshalb nur die relevanten Codeabschnitte zu posten um den Aufwand möglichst gering zu halten. Dass das Icon Probleme macht konnte ich eingangs nicht wissen, da es in meiner Lösung nichts mit dem Menü zu tun hatte. (Waren ja zwei getrennte Menüs sie seperate inflated wurden)