4

Я могу успешно перехватывать кнопку ActionBar домой из NavigationDrawerFragment, который добавляется к моему MainActivity, вот так:кнопку Перехват ActionBar дома в Fragment

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    if (!loggedIn() && item.getItemId() == android.R.id.home) { 
     login(); 
     return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

Однако, в моем ComposeActivity с ComposeFragment это не работает. onOptionsItemSelected не вызывается для фрагмента.

Я отлаживал код, и проблема, похоже, сводится к дизайну библиотеки поддержки Android. Похоже, что и у FragmentActivity, и у Activity есть свои ссылки на FragmentManager.

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

/** 
* Dispatch context and options menu to fragments. 
*/ 
@Override 
public boolean onMenuItemSelected(int featureId, MenuItem item) { 
    if (super.onMenuItemSelected(featureId, item)) { 
     return true; 
    } 

    switch (featureId) { 
     case Window.FEATURE_OPTIONS_PANEL: 
      return mFragments.dispatchOptionsItemSelected(item); 

     case Window.FEATURE_CONTEXT_MENU: 
      return mFragments.dispatchContextItemSelected(item); 

     default: 
      return false; 
    } 
} 

Как видно в приведенном ниже фрагменте кода Activity обрабатывает кнопку домой в крайнем случае , после проверки того, сможет ли он или любой из его фрагментов обработать событие. Но эта ссылка на FragmentManager не содержит фрагментов, фрагменты находятся в менеджере FragmentActivity. Поэтому событие будет проглочено классом Activity, если установлено ActionBar.DISPLAY_HOME_AS_UP.

public boolean onMenuItemSelected(int featureId, MenuItem item) { 
    /* ... */ 
    if (onOptionsItemSelected(item)) { 
     return true; 
    } 
    if (mFragments.dispatchOptionsItemSelected(item)) { 
     return true; 
    } 
    if (item.getItemId() == android.R.id.home && mActionBar != null && 
      (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { 
     if (mParent == null) { 
      return onNavigateUp(); 
     } else { 
      return mParent.onNavigateUpFromChild(this); 
     } 
    } 
    return false; 
    /* ... */ 
} 

Оказывается, что мой MainActivity, будучи корнем моего приложения и с помощью панели навигации, не имеют этот флаг установлен, и поэтому не проглотит событие. Но мой ComposeActivity имеет родительскую активность, и мне нужно установить этот флаг, чтобы не было возможности перехватить кнопку панели действий.

Резюмируя вопрос: Это невозможно перехватить нажатие на кнопку панели действий дома из фрагмента в деятельности с с набором DISPLAY_HOME_AS_UP.

Так это ошибка в библиотеке поддержки? Не похоже, что это произойдет, если я нацелен на более позднюю версию Android и бросил библиотеку поддержки.

Что касается обходных путей для этого, я думаю, я мог бы:

  • В моих ComposeActivity «ы onOptionsItemSelected я могу вручную передать событие каждому из моих фрагментов, видя, если они могут справиться с этим перед вызовом супер.
  • Переопределить onMenuItemВыбрать в ComposeActivity и сделать то же самое.

Кто-нибудь сталкивался с этим раньше? Должен ли я где-нибудь регистрировать ошибку? Какие-нибудь другие идеи об этом вопросе?

+1

ли вы решить эту проблему? Я пытаюсь обработать 'android.R.id.home' в фрагменте' onOptionsItemSelected() ', но он никогда не достигает фрагмента. – Delblanco

+0

http://stackoverflow.com/questions/15035861/fragment-onoptionsitemselected-not-being-called?rq=1 может помочь – Delblanco

+0

В настоящее время я получаю действие 'android.R.id.home' в базовом действии и передавая его всем фрагментам до вызова метода super. Обходной путь. – darnmason

ответ

4

Как вы объяснили, из-за потока событий, отправленных на Android, кажется, что дочерний фрагмент никогда не будет перехватывать событие, потому что он сначала используется Activity.

Это обходное решение, но то, что я делаю, передает событие дочерним фрагментам, прежде чем обрабатывается в Activity.

В деятельности:

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Due to a problem of not being able to intercept android.R.id.home in fragments, 
    // we start passing the event to the currently displayed fragment. 
    // REF: http://stackoverflow.com/questions/21938419/intercepting-actionbar-home-button-in-fragment 
    final Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.XXXXXXX); 
    if (currentFragment != null && currentFragment.onOptionsItemSelected(item)) { 
     return true; 
    } 

    switch (item.getItemId()) { 
     case XXX: 
      ... 
      return true; 
     case YYY: 
      ... 
      return true; 
     default: 
      break; 
    } 
    return super.onOptionsItemSelected(item); 
} 
+0

Какой легкий и отличный хакерский способ сделать это ... Спасибо, что работает хорошо для моей проблемы. – Manisha

Смежные вопросы