82

我開始使用v7支持庫中的AppCompat/ActionBarCompat的新項目。我試圖弄清楚如何在片段中使用getSupportActionBar。我的活動承載的片段延伸ActionBarActivity,但我沒有看到類似的支持類的碎片。從片段內部獲取ActionSupportActionBar ActionBarCompat

從我的片段

public class CrimeFragment extends Fragment { 
      //... 

      getActivity().getSupportActionBar().setSubtitle(R.string.subtitle); // getSupportActionBar is not defined in the v4 version of Fragment 

      //... 
    } 

的谷歌網頁使用它(http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html)中說,有應爲v4片段沒有改變。我是否需要將我所有的getActivity()電話都撥到ActionBarActivity?這似乎是糟糕的設計。

+0

可以解釋一下你是如何解決這個問題的? –

回答

229

經過Fragment.onActivityCreated(...)您將擁有可通過getActivity()訪問的有效活動。

您需要將其轉換爲ActionBarActivity,然後調用getSupportActionBar()。

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle); 

您確實需要演員。這不是糟糕的設計,而是向後兼容。

+3

謝謝。我希望這不會是答案。我希望也許那個getActionBar()會返回一個v7 ActionBar,如果我需要額外的功能,我會投入。現在我的碎片必須知道它們託管的是哪種類型的活動。 – Paul

+0

不,它不是因爲getActionBar()是舊版SDK(早期蜂窩)中不存在的活動API。這就是爲什麼我們需要支持類來反映更新SDK中新的和改進的類和API的功能。 –

+0

@ Pierre-AntoineLaFayette爲什麼必須在onAttach()中完成? onActivityCreated()會不會更好? –

33

儘管這個問題有一個公認的答案了,我必須指出,這是不完全正確:從Fragment.onAttach()調用getSupportActionBar()會導致NullPointerException活動時旋轉。

簡短的回答:

使用((ActionBarActivity)getActivity()).getSupportActionBar()onActivityCreated()(或在其生命週期之後的任何點),而不是onAttach()

龍答:

的原因是,如果ActionBarActivity是旋轉後重建,這將恢復所有碎片前實際創建ActionBar對象。在support-v7ActionBarActivity

的源代碼:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mImpl = ActionBarActivityDelegate.createDelegate(this); 
    super.onCreate(savedInstanceState); 
    mImpl.onCreate(savedInstanceState); 
} 
  • ActionBarActivityDelegate.createDelegate()創建取決於Android版本的mImpl對象。
  • super.onCreate()FragmentActivity.onCreate(),其在旋轉後恢復任何先前的片段(FragmentManagerImpl.dispatchCreate(),&c)。
  • mImpl.onCreate(savedInstanceState)ActionBarActivityDelegate.onCreate(),它從窗口樣式讀取mHasActionBar變量。
  • mHasActionBar爲真之前,getSupportActionBar()將始終返回null

ActionBarActivityDelegate.getSupportActionBar()來源:

final ActionBar getSupportActionBar() { 
    // The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar 
    // could change after onCreate 
    if (mHasActionBar || mOverlayActionBar) { 
     if (mActionBar == null) { 
      ... creates the action bar ... 
     } 
    } else { 
     // If we're not set to have a Action Bar, null it just in case it's been set 
     mActionBar = null; 
    } 
    return mActionBar; 
} 
25

如果有人使用com.android.support:appcompat-v7:和AppCompatActivity的活動,那麼這將工作

((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle); 
1

fragment.xml添加Toolbar支持庫中的標記

<android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:layout_collapseMode="pin" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> 

現在我們如何從MyFragment類中控制它呢?讓我們來看看

onCreateView函數中添加以下

mToolbar = (Toolbar) view.findViewById(R.id.toolbar); 
((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar); 

//add this line if you want to provide Up Navigation but don't forget to to 
//identify parent activity in manifest file 
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); 

,如果你想要從MyFragment 添加items到工具欄,你must裏面添加onCreateView功能

 setHasOptionsMenu(true); 

這條線是這條線重要的是,如果你忘記它,android不會填充你的菜單項。

假設,我們確定他們menu/fragment_menu.xml

後覆蓋以下功能

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

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    int id = item.getItemId(); 
    switch (id) { 
     case R.id.action_1: 
      // do stuff 
      return true; 

     case R.id.action_2: 
      // do more stuff 
      return true; 
    } 

    return false; 
} 

希望這有助於

0

一個更新的答案皮埃爾 - 安託萬·拉斐特的回答

ActionBarActivity是棄用;用AppCompatActivity代替

((AppCompatActivity)getActivity()).getSupportActionBar();