(Не застосовується) Фрагмент onOptionsItemSelected не викликається


82

EDIT: Це питання стосувалось застарілої панелі дій sherlock. Замість цього зараз слід використовувати бібліотеку підтримки Android

Я додав опцію меню панелі дій під назвою спільний доступ до моєї, fragmentяка з’являється, але подія виділення не ловиться

Я додаю це так

@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);
}

Спроба зафіксувати це як у тому, так fragmentі тому fragment activityподібному

@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);
    }
}

і я маю setHasOptionsMenu(true);в onCreate().

Відповіді:


145

У мене трапились ті самі проблеми:

onMenuItemSelected події не викликаються у фрагменті

Шуканий Google не може знайти рішення, і додавання методу onMenuItemSelected у FragmentActivity його не вирішує.

Нарешті, вирішіть це, перейшовши за посиланням http://developer.android.com/guide/topics/ui/actionbar.html

Примітка: Якщо ви додали пункт меню із фрагмента через зворотний виклик класу Fragment onCreateOptionsMenu, тоді система викликає відповідний метод onOptionsItemSelected () для цього фрагмента, коли користувач вибирає один із елементів фрагмента. Однак активність отримує шанс обробити подію першою, тому система викликає onOptionsItemSelected () щодо активності, перш ніж викликати той самий зворотний виклик для фрагмента.

Це означає, що лише якщо у вас немає цього обробника елемента меню в onOptionsItemSelected () щодо діяльності, буде викликано onOptionsItemSelected () у фрагменті.

Код наступний ----- Видаліть обробник для R.action.add на 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);
    }   
}

А обробник для R.action.add на Fragment виглядає так:

@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);
    }
}

Нарешті, не забудьте додати

    setHasOptionsMenu(true);

у вашому методі onCreate у фрагменті


12
Для мене, щоб перехопити натискання меню на фрагменті, мені довелося повернути "false" на onOptionsItemSelected з FragmentActivity та на onOptionsItemSelected з фрагмента, виконати бажану поведінку.
Едісон Сантос

1
фрагмент із setHasOptionsMenu (істина); у методі onCreate та загальнодоступному логічному onOptionsItemSelected (пункт MenuItem) {} зробив магію
Moisés

@Felixqk У мене такі проблеми із фрагментами. У мене є два фрагменти. Але фрагмент 2 OnOptionsSelectedItem не викликається. Фрагмент 2 відображає пункт меню фрагмента 1.
Roon13

@ Roon13 Видалити super.onCreateOptionsMenu; з фрагмента onCreateOptionsMenu. + setHasOptionsMenu (істина); працював у мене, не видаляючи Activity onOptionsItemSelected.
ахмадалібалох

129

У мене була та ж проблема, але я вважаю, що краще підвести підсумок і ввести останній крок, щоб це запрацювало:

  1. Додайте setHasOptionsMenu(true)метод у метод вашого фрагмента onCreate(Bundle savedInstanceState).

  2. Замінити onCreateOptionsMenu(Menu menu, MenuInflater inflater)(якщо ви хочете зробити щось інше в меню вашого фрагмента) та onOptionsItemSelected(MenuItem item)методи у вашому фрагменті.

  3. Усередині onOptionsItemSelected(MenuItem item)методу Вашої активності переконайтеся, що Ви повертаєтесь, falseколи дія пункту меню буде реалізована у onOptionsItemSelected(MenuItem item)методі Фрагменту .

Приклад:

Діяльність

@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;
}

Фрагмент

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;
}

6
return falseна Діяльність onOptionItemSelected- це ключ. просто замінитиreturn super.onOptionItemSelected(item);
Youngjae

1
Працює ідеально. Дякую Марко.
Раджеєв Саху

2
Чудова відповідь. Вам слід змінити onCreateOptionsMenu (меню меню) на onCreateOptionsMenu (меню меню, надувач MenuInflater), коли він у фрагменті
Chris Sprague

1
Це чудове рішення. Thnakx Marco HC
Darsh Patel

1
Чудове рішення, друже! Слава!
Хан Тран

5

Я помітив, що рішення, яке вам запропонували люди, полягало в тому, щоб впровадити код для вашого елемента меню в активність, а не фрагмент. Я думаю, це буде виглядати набагато більш організованим, якби ви застосували код у фрагменті, а не діяльність, оскільки, на мій погляд, це виглядає краще. Для цього виконайте наступне:

Діяльність

@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;
    }

Фрагмент

 @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;
        }

Тепер рядки (і лайки): "return super.onOptionsItemSelected (item);" в діяльності та фрагменті надзвичайно важливі, тому що як якщо ви будете слідувати коду під час налагодження, ви побачите, що функції подій меню будуть викликані спочатку в Activity, а якщо елемент не відповідає ідентифікаторам у перемикачі діяльності- case, рядок за замовчуванням: "super.onOptionsItemSelected (item);" буде викликати функцію onOptionsItemSelected на фрагменті, як ми і хотіли. (якщо у вас багато фрагментів, переконайтеся, що в них є і ця лінія, оскільки виклик ірархії може бути дещо складним).


2

Я використовую actionbarsherlock. Це спрацювало для мене:

1) Створіть меню 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) Під час активності роздуйте меню так:

@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) У фрагментах onCreateView виклику setHasOptionsMenu (істина) та перевизначенні onCreateOptionsMenu та onOptionsItemSelected також сховати манекен Меню так (у фрагменті)

    @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);
}

Сподіваюся, це комусь допомагає.


2

Редагувати для використання шерлока на панелі дій

Мені довелося скористатися

public boolean onMenuItemSelected(int featureId, MenuItem item) {

в основному захопі захоплення пункту меню


Та сама проблема, і вона також вирішена для мене, дякую. Чи можете ви сказати, чому onOptionItemSelected не працював?
nadeem gc

Тому що на панелі дій
sherlock

Змініть onMenuItemSelected для виклику onOptionItemSelected, щоб ваш код працював при переході з ABS на appcompatlib
slott

1
@nadeemgc причина, по якій це не працює, полягає в тому, що Android знає про два типи меню: меню параметрів та контекстне меню. Панель дій Шерлок використовує контекстне меню, яке викликає onContextItemSelectedзамість onOptionsItemSelected. onMenuItemSelectedПросто пересилає натисніть на правильний метод, тому він , як видається , краще працювати.
Amru E.

@AmruE. Дякую, це буде корисним у майбутньому.
nadeem gc

2

це настільки просто, що ви можете зробити це у своєму фрагменті, щоб переконатися, що ваша дія буде прослухана правильно:

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

0

У мене була ця проблема. Це було тому, що я перекривав неправильний метод

onOptionsItemSelected (елемент com.actionbarsherlock.view.MenuItem) - це те, що я використовував.

Переконайтеся, що ви використовуєте правильний!


0

Ви не приковані до суперкласу в методах діяльності. Будь ласка, поверніть onCreateOptionsMenu () повернення super.onCreateOptionsMenu (меню) і onOptionsItemSelected () поверніть super.onOptionsItemSelected (item) (за винятком елемента, яким ви обробляєте, який повинен повернути true, щоб вказати, що ви обробили подію)


0

Ви повинні додати цей код toolbar.bringToFront();наступного набору панелей інструментів у свою діяльність

 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
         ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.