(Przestarzałe) Fragment onOptionsItemSelected nie jest wywoływany

82

EDYCJA: To pytanie dotyczyło wycofanego paska akcji Sherlocka. Zamiast tego należy teraz użyć biblioteki obsługi systemu Android

Dodałem opcję menu paska akcji o nazwie udostępnij dla mojego, fragmentktóra pojawia się, ale zdarzenie selekcji nie jest przechwytywane

Dodam to w ten sposób

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
    MenuItem item = menu.add(0, 7,0, R.string.share);
    item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}

Próbując uchwycić to zarówno w jak fragmenti tym fragment activitypodobnych

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case 7:
            Intent share = new Intent(Intent.ACTION_SEND);
            share.setType("text/plain");
            share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
            startActivity(Intent.createChooser(share, "Share Text"));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

i mam setHasOptionsMenu(true);w onCreate().

user1634451
źródło

Odpowiedzi:

145

Przydarzyły mi się te same problemy:

Zdarzenia onMenuItemSelected nie zostały wywołane we fragmencie

Wyszukiwana wyszukiwarka Google nie może znaleźć rozwiązania, a dodanie metody onMenuItemSelected w FragmentActivity go nie rozwiązuje.

Na koniec rozwiąż ten problem, postępując zgodnie z odniesieniem do http://developer.android.com/guide/topics/ui/actionbar.html

Uwaga: Jeśli dodałeś pozycję menu z fragmentu, poprzez wywołanie zwrotne onCreateOptionsMenu klasy Fragment, to system wywoła odpowiednią metodę onOptionsItemSelected () dla tego fragmentu, gdy użytkownik wybierze jeden z elementów fragmentu. Jednak działanie ma szansę obsłużyć zdarzenie jako pierwsze, więc system wywołuje metodę onOptionsItemSelected () na działaniu przed wywołaniem tego samego wywołania zwrotnego dla fragmentu.

Oznacza to, że tylko jeśli nie masz tego modułu obsługi pozycji menu w onOptionsItemSelected () w działaniu, zostanie wywołana onOptionsItemSelected () we fragmencie.

Kod w następujący sposób ----- Usuń procedurę obsługi dla R.action.add na FragmentActivity):

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case android.R.id.home:
            popBackStack();             
            return true;        
        case R.id.action_search:
            searchAction();
            return true;
        case R.id.action_logout:
            userLogout();
            return true;
        //case R.id.action_add:
            //return true;    
        default:
            return super.onOptionsItemSelected(item);
    }   
}

A handler dla R.action.add on Fragment wygląda tak:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d("onOptionsItemSelected","yes");
    switch (item.getItemId()) {
        case R.id.action_add:
            add();
            return true;    
        default:
            return super.onOptionsItemSelected(item);
    }
}

Na koniec pamiętaj, aby dodać

    setHasOptionsMenu(true);

w metodzie onCreate w Fragment

Felixqk
źródło
12
Dla mnie, aby przechwycić menu kliknij na fragment, musiałem zwrócić „false” na onOptionsItemSelected elementu FragmentActivity i na onOptionsItemSelected fragmentu, wykonać żądane zachowanie.
Edison Santos
1
fragment z setHasOptionsMenu (true); in onCreate i public boolean onOptionsItemSelected (MenuItem item) {} metoda zrobiła magię
Moisés
@Felixqk Mam taki problem z fragmentami. Mam dwa fragmenty. Ale OnOptionsSelectedItem fragmentu 2 nie jest wywoływana. Fragment 2 pokazuje opcję menu fragmentu 1.
Roon13
@ Roon13 Usuń super.onCreateOptionsMenu; z fragmentu onCreateOptionsMenu. + setHasOptionsMenu (true); pracował dla mnie bez usuwania Activity onOptionsItemSelected.
ahmadalibaloch
129

Miałem ten sam problem, ale myślę, że lepiej podsumować i przedstawić ostatni krok, aby to zadziałało:

  1. Dodaj setHasOptionsMenu(true)metodę w metodzie fragmentu onCreate(Bundle savedInstanceState).

  2. Zastąp onCreateOptionsMenu(Menu menu, MenuInflater inflater)(jeśli chcesz zrobić coś innego w menu swojego fragmentu) i onOptionsItemSelected(MenuItem item)metody w swoim fragmencie.

  3. Wewnątrz onOptionsItemSelected(MenuItem item)metody działania upewnij się, że powrócisz, falsegdy akcja elementu menu zostanie zaimplementowana w onOptionsItemSelected(MenuItem item)metodzie Fragment .

Przykład:

Czynność

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.activity_menu_item:
        // Do Activity menu item stuff here
        return true;
    case R.id.fragment_menu_item:
        // Not implemented here
        return false;
    default:
        break;
    }

    return false;
}

Fragment

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    ....
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.activity_menu_item:
        // Not implemented here
        return false;
    case R.id.fragment_menu_item:
        // Do Fragment menu item stuff here
        return true;
    default:
        break;
    }

    return false;
}
Marco HC
źródło
6
return falsena Aktywności onOptionItemSelectedjest kluczem. wystarczy wymienićreturn super.onOptionItemSelected(item);
Youngjae,
1
Działa idealnie. Dzięki Marco.
Rajeev Sahu
2
Świetna odpowiedź. Powinieneś zmienić onCreateOptionsMenu (menu menu) na onCreateOptionsMenu (menu menu, MenuInflater inflater), gdy jest we fragmencie
Chris Sprague
1
To świetne rozwiązanie. Thnakx Marco HC
Darsh Patel
1
Świetne rozwiązanie, przyjacielu! Dzięki!
Han Tran
5

Zauważyłem, że rozwiązaniem, które dali ci ludzie, było zaimplementowanie kodu dla twojego elementu menu w ćwiczeniu, a nie fragmentu. Myślę, że wyglądałoby to na znacznie bardziej zorganizowane, gdybyś zaimplementował kod we fragmencie, a nie działanie, bo moim zdaniem wygląda lepiej. Aby to zrobić, wykonaj następujące czynności:

Czynność

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

 @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {            
        switch (item.getItemId())
        {
            case R.id.SomeIDInTheMenueOfTheActivity:
            {
               //something();
                break;
            }
            default:
             //do something default and add the code under : 
             return super.onOptionsItemSelected(item);
        }
        return true;
    }

Fragment

 @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);  
            setHasOptionsMenu(true);      
        }

  @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {           
        super.onCreateOptionsMenu(menu, inflater);
    }

     @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {
            switch (item.getItemId())
            {           
                case R.id.SomeIDInFragmentMenue:
                {             
                    break;
                }

                default:
                    return super.onOptionsItemSelected(item);
            }

            return true;
        }

Teraz wiersze (i polubienia): "return super.onOptionsItemSelected (item);" w działaniu i fragment są bardzo ważne, ponieważ tak jakbyś podążał za kodem podczas debugowania, zobaczysz, że funkcje zdarzeń menu zostaną wywołane jako pierwsze w działaniu, a jeśli element nie będzie pasował do identyfikatorów w przełączniku działania case, wiersz degault: "super.onOptionsItemSelected (item);" wywoła funkcję onOptionsItemSelected na fragmencie, tak jak chcieliśmy. (jeśli masz wiele fragmentów, upewnij się, że masz w nich również tę linię, ponieważ hirarchia wywoływania może być nieco skomplikowana).

Malfonde
źródło
2

Używam actionbarsherlock. To zadziałało dla mnie:

1) Utwórz menu dummy_menu.xml

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

<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
      android:title=""
      android:showAsAction="never"
      android:id="@+id/dummyMenu"
        />

2) W aktywności napompuj menu w ten sposób:

@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
    com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.dummy_menu,menu);
   return super.onCreateOptionsMenu(menu);
}

3) We fragmentach wywołania onCreateView setHasOptionsMenu (true) i przesłonięcia onCreateOptionsMenu i onOptionsItemSelected również ukryj dummyMenu w ten sposób (we fragmencie)

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

Mam nadzieję, że to komuś pomoże.

okkko
źródło
2

Edytuj, aby użyć paska akcji Sherlock

Musiałem użyć

public boolean onMenuItemSelected(int featureId, MenuItem item) {

w głównym działaniu, aby uchwycić element menu

user1634451
źródło
Ten sam problem i dla mnie również rozwiązany, dzięki. Czy możesz powiedzieć, dlaczego onOptionItemSelected nie działa?
nadeem gc,
Ponieważ pasek akcji
Sherlock
Zmień onMenuItemSelected, aby wywołać onOptionItemSelected, aby kod działał podczas przechodzenia z ABS do appcompatlib
slott
1
@nadeemgc powodem, dla którego nie działa, jest to, że Android zna dwa typy menu: menu opcji i menu kontekstowe. Actionbar Sherlock używa menu kontekstowego, które wywołuje onContextItemSelectedzamiast onOptionsItemSelected. Po onMenuItemSelectedprostu przekazuje kliknięcie do właściwej metody, dlatego wydaje się, że działa lepiej.
Amru E.
@AmruE. Dziękuję, będzie pomocna w przyszłości.
nadeem gc
2

jest to tak proste, że możesz to zrobić w swoim fragmencie, aby upewnić się, że Twoja akcja będzie poprawnie nasłuchiwała:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}
Mohamed Hussien
źródło
0

Miałem ten problem. To dlatego, że wybrałem złą metodę

Użyłem onOptionsItemSelected (com.actionbarsherlock.view.MenuItem item).

Upewnij się, że używasz właściwego!

Barrie Galitzky
źródło
0

W metodach aktywności nie przywiązujesz się do superklasy. Proszę mieć onCreateOptionsMenu () return super.onCreateOptionsMenu (menu) i mieć onOptionsItemSelected () return super.onOptionsItemSelected (item) (z wyjątkiem pozycji, którą obsługujesz, która powinna zwrócić true, aby wskazać, że obsłużyłeś zdarzenie)

Divyesh V.Murani
źródło
0

musisz dodać ten kod do toolbar.bringToFront();następnego zestawu narzędzi w swoim działaniu

 public class MainActivity extends AppCompatActivity {
     protected void onCreate(Bundle savedInstanceState) {
        ...

        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle("Yazd");
        setSupportActionBar(toolbar);
        toolbar.bringToFront(); // <<= add here
         ...
Mahdi Afkhami
źródło