Фрагмент, не получающий обратные вызовы меню - PullRequest
39 голосов
/ 08 июня 2011

У меня есть фрагментный класс, который расширяет Fragment и вызывает setHasOptionsMenu для участия в меню. Этот класс также реализует onCreateOptionsMenu, onPrepareOptionsMenu и onOptionsItemSelected.

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

Я динамически загружаю этот фрагмент, используя FragmentTransaction в моей Деятельности (которая расширяет FragmentActivity).

Однако ни один из обратных вызовов меню (onCreateOptionsMenu, onPrepareOptionsMenu и onOptionsItemSelected) не вызывается (я отлаживал с некоторыми точками останова в этих методах), и меню не отображается.

Я что-то упустил? Нужно ли что-то добавить в свою активность?

Я использую библиотеку совместимости Android, компилирую с L11 SDK и тестирую в Xoom.

РЕДАКТИРОВАТЬ : Я нашел проблему. Мой AndroidManifest ориентирован на L11, это, кажется, скрывает кнопку меню и предотвращает обратные вызовы. Однако, если я удаляю это из манифеста, я теряю некоторые другие необходимые мне функции (например, активированное состояние в списках). Кто-нибудь знает, как решить эту проблему (включить кнопку меню), не удаляя targetSdkVersion=11 из манифеста?

Ответы [ 12 ]

29 голосов
/ 08 июня 2011

Aromero, Не забудьте переопределить onCreateOptionsMenu, используя фрагментную версию метода, подобную этой:

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

Кстати, это происходит во фрагменте и добавляется в раздутое меню Действия, если оно есть. У меня была такая же проблема, пока я не понял это.

Kim

9 голосов
/ 19 августа 2013

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

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

  2. Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (если вы хотите сделать что-то другое в меню вашего фрагмента) и onOptionsItemSelected(MenuItem item) методы в вашем фрагменте.

  3. Внутри onOptionsItemSelected(MenuItem item) метода Activity, убедитесь, что вы возвращаете false, когда действие элемента меню будет реализовано в onOptionsItemSelected(MenuItem item) методе Fragment.

Пример:

Активность

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

Я надеюсь, что это будетполезно.

ура.

9 голосов
/ 25 января 2013

Если у вас возникла эта проблема с ActionBarSherlock, вам нужно убедиться, что ваши фрагменты являются SherlockFragments, а не просто SupportFragments, и что вы переопределяете это

public void onPrepareOptionsMenu (com.actionbarsherlock.view.Menu menu) {

НЕ

public void onPrepareOptionsMenu (android.view.Menu menu) {

Если вы сделаете последнее, вы должны получить какое-то предупреждение о том, что функция является окончательной, и вы не можете ее переопределить. Это предупреждение о том, что вы пытаетесь переопределить неправильную функцию!

Если вы исправите ошибку, переключив класс с SherlockFragment на простой Fragment, вы можете создать функцию. , , но это не будет вызвано.

6 голосов
/ 11 сентября 2012

Если у вас есть действие и фрагмент, каждый из которых загружает пункты меню, вам нужно позаботиться о том, какие переопределения вы используете.

Действия могут переопределять onOptionsItemSelected и onMenuItemSelected , однако фрагменты могут переопределять только onOptionsItemSelected .

Если вы переопределите onMenuItemSelected в своей активности и onOptionsItemSelected в своем фрагменте, переопределение вашего фрагмента никогда не сработает.

Вместо этого используйте onOptionsItemSelected как в действии, так и во фрагменте.

5 голосов
/ 06 ноября 2012

Вы должны убедиться, что вы звоните setHasOptionsMenu(true); onCreate или onCreateView вызывается в вашем фрагменте.

Вам также нужно реализовать переопределение onCreateOptionsMenu внутри вашего фрагмента.

4 голосов
/ 04 февраля 2014

Другой возможный случай - когда вы используете общий идентификатор для общего действия в каждом фрагменте; например R.id.action_add

Сегодня у меня была такая ситуация: при нажатии меню параметров [добавить] вызывался «неправильный» onOptionItemSelected, поскольку каждый фрагмент (динамически замененный с помощью DrawerLayout) имел одинаковые R.id.action_add.

Короткая история, если у вас такая ситуация, всегда проверяйте, виден ли ваш фрагмент:

if (!isVisible()) return false;

Длинная история, обратите внимание на onOptionItemSelected цепочку!

  MainActivity
       |
       |  onOptionItemSelected
       +-----------------------
       |     return false
       |
 MyCoolFragment1
       |
       |  onOptionItemSelected
       +-----------------------
       |     return false
       |
 MyCoolFragment2
       |
       |  onOptionItemSelected
       +-----------------------
       |     return true
       |
[item selection handled]

Если вы добавите свои фрагменты с помощью (что-то вроде) этого:

getSupportFragmentManager()
   .beginTransaction()
   .replace(R.id.content_frame, MyCoolFragment1.newInstance())
   .commit() 

и вы определили один и тот же идентификатор для общего действия (скажем, R.id.action_add) в каждом фрагменте; не забудьте добавить эту строку к каждому: if (! isVisible ()) вернет false;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (!isVisible()) return false; // <-- Not visible? skip!

    if (item.getItemId() == R.id.action_add) {
        //.TODO whatever
        return true;  //.Handled!
    }

    return false; //.Skip
}
3 голосов
/ 12 июля 2012

У меня была эта проблема, когда я использовал ViewPagerIndicator вместе с ActionBarSherlock.Хотя оказалось, что это исправлено Я все же столкнулся с проблемой.Обходной путь, который я нашел, заключался в том, чтобы вызвать фрагмент вручную.

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    Toast.makeText(this, "From activity", Toast.LENGTH_SHORT).show(); // TODO
    Fragment currentFragment = mAdapter.getItem(mPager.getCurrentItem());
    if (currentFragment != null && currentFragment instanceof SherlockFragment)
    {
        ((SherlockFragment)currentFragment).onOptionsItemSelected(item);
    }
    return super.onOptionsItemSelected(item);

}
2 голосов
/ 12 июня 2011

Я нашел проблему.AndroidManifest нацелен на SDK 11, это, кажется, скрывает кнопку меню и предотвращает обратные вызовы.Я предполагаю, что это нарушает совместимость кнопки меню, которая, кажется, заменена панелью действий в Android 3.0

1 голос
/ 29 августа 2017

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

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    ....
    Toolbar toolbar = (Toolbar)getActivity().findViewById(R.id.toolbar);
    ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
    setHasOptionsMenu(true);
}

И затем, конечно, переопределите onCreateOptionsMenu, как показано ниже

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

Этоэто единственное решение, которое сработало для меня!

1 голос
/ 30 октября 2014

С сайта разработчика Android - ссылка

Примечание: если вы раздуваете пункты меню из фрагмента, через фрагмент обратный вызов класса onCreateOptionsMenu (), системные вызовы onOptionsItemSelected () для этого фрагмента, когда пользователь выбирает один из эти предметы. Тем не менее, деятельность получает возможность обработать событие во-первых, система сначала вызывает onOptionsItemSelected () на активность, перед вызовом того же обратного вызова для фрагмента . Для обеспечения что любые фрагменты в деятельности также имеют возможность обрабатывать обратный вызов, всегда передавайте вызов суперклассу по умолчанию поведение вместо возврата false , когда вы не обрабатываете элемент.

Поэтому Марко ХК - лучший ответ из всех.

...