4

我可以成功攔截從我NavigationDrawerFragmentActionBar home鍵,這是添加到我的MainActivity,像這樣:攔截動作條主頁按鈕,在片段

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

然而,在我ComposeActivityComposeFragment這不起作用。片段上未調用onOptionsItemSelected

我調試了代碼,問題似乎歸結爲Android支持庫的設計。看起來FragmentActivityActivity都有自己對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處理home鍵作爲最後的手段在檢查它或它的任何碎片是否可以處理事件之後。但是這個FragmentManager的引用不包含任何片段,片段位於FragmentActivity的管理器中。因此,如果設置了ActionBar.DISPLAY_HOME_AS_UP,該事件將被Activity課程吞噬。

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版本並刪除支持庫,它看起來不會發生。

這對於解決方法,我想我可以:

  • 在我ComposeActivityonOptionsItemSelected我可以在事件人工傳遞給我的每一個片段,看他們是否可以在調用超之前處理它。
  • 覆蓋onmenuItemSelected並做同樣的事情。

有人遇到過這個嗎?我應該在哪裏登錄一個bug?有關解決此問題的其他方法?

+1

你解決這個問題?我試圖在片段的onOptionsItemSelected()中處理'android.R.id.home',但它永遠不會到達片段。 – Delblanco

+0

http://stackoverflow.com/questions/15035861/fragment-onoptionsitemselected-not-being-called?rq=1可能會幫助 – Delblanco

+0

我目前正在接收基本活動中的android.R.id.home動作,在調用超級方法之前將它傳遞給所有片段。解決方法。 – darnmason

回答

4

正如您所解釋的,由於Android中調度事件的流程,似乎子片段永遠不會攔截該事件,因爲它首先被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