it-swarm.com.ru

(Устарело) Фрагмент onOptionsItemSelected не вызывается

Правка: Этот вопрос был для устаревшей панели действий Шерлока. Вместо этого следует использовать библиотеку поддержки Android

Я добавил опцию меню панели действий под названием share для моего 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().

80
user1634451

Редактировать для использования панели действий Шерлока

Я должен был использовать 

public boolean onMenuItemSelected(int featureId, MenuItem item) {

в основной деятельности, чтобы захватить пункт меню 

2
user1634451

Те же проблемы произошли со мной: 

события onMenuItemSelected не были вызваны во фрагменте

Поисковый Google не может найти решение, и добавить метод onMenuItemSelected во FragmentActivity это не решает.

В конце концов, решите проблему, перейдя по ссылке http://developer.Android.com/guide/topics/ui/actionbar.html

Примечание. Если вы добавили элемент меню из фрагмента с помощью обратного вызова onCreateOptionsMenu класса Fragment, тогда система вызывает соответствующий метод 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 во фрагменте

145
Felixqk

У меня была та же проблема, но я думаю, что лучше подвести итог и представить последний шаг, чтобы она заработала:

  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;
}
125
Marco HC

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

Деятельность

@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, строка degault: "super.onOptionsItemSelected (item);" вызовет функцию onOptionsItemSelected для фрагмента, как мы и хотели . (если у вас много фрагментов, убедитесь, что в них также есть эта строка, так как вызывающая иерархия может быть несколько сложной).

5
Malfonde

это так просто, что вы можете сделать это в своем фрагменте, чтобы убедиться, что ваше действие будет слушать правильно:

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

Я использую 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 (true) и переопределяют onCreateOptionsMenu, а onOptionsItemSelected также скрывают dummyMenu следующим образом (во фрагменте)

    @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
okkko

У меня была эта проблема. Это потому, что я переопределил неправильный метод

onOptionsItemSelected (элемент com.actionbarsherlock.view.MenuItem) это то, что я использовал.

Убедитесь, что вы используете правильный!

0
Barrie Galitzky

Вы не цепляетесь за суперкласс в методах действия. Пусть onCreateOptionsMenu () возвращает super.onCreateOptionsMenu (menu), а onOptionsItemSelected () возвращает super.onOptionsItemSelected (item) (кроме элемента, который вы обрабатываете, который должен возвращать true, чтобы указать, что вы обработали событие)

0
Divyesh Murani