从片段ActionBarCompat中获取getSupportActionBar

我开始一个使用AppCompat/ActionBarCompat v7支持库的新项目。 我想弄清楚如何使用片段内的getSupportActionBar 。 我的活动,承载片段扩展ActionBarActivity ,但我没有看到类似的支持类的碎片。

从我的片段中

  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 ? 这似乎是糟糕的devise。

在Fragment.onActivityCreated(…)之后,您将拥有可通过getActivity()访问的有效活动。 您需要将其转换为ActionBarActivity,然后调用getSupportActionBar()。

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

你确实需要演员。 这不是糟糕的devise,它是向后兼容的。

虽然这个问题已经有了一个可以接受的答案,但我必须指出,这不是完全正确的:调用Fragment.onAttach() getSupportActionBar() Fragment.onAttach()会导致一个NullPointerException

简短的回答:

onActivityCreated() (或其生命周期中的任意点((ActionBarActivity)getActivity()).getSupportActionBar()中使用((ActionBarActivity)getActivity()).getSupportActionBar() )而不是onAttach()

很长的回答:

原因是如果在ActionBarActivity之后重新创build一个ActionBarActivity ,它将实际创buildActionBar对象之前恢复所有的Fragment。

support-v7库中的ActionBarActivity源代码:

 @Override protected void onCreate(Bundle savedInstanceState) { mImpl = ActionBarActivityDelegate.createDelegate(this); super.onCreate(savedInstanceState); mImpl.onCreate(savedInstanceState); } 
  • ActionBarActivityDelegate.createDelegate()根据Android版本创buildmImpl对象。
  • super.onCreate()FragmentActivity.onCreate() ,它在一个旋转之后恢复任何以前的片段( FragmentManagerImpl.dispatchCreate() ,&c)。
  • mImpl.onCreate(savedInstanceState)ActionBarActivityDelegate.onCreate() ,它从窗口样式读取mHasActionBarvariables。
  • mHasActionBar为true之前, 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; } 

如果有人使用com.android.support:appcompat-v7:和AppCompatActivity作为活动,那么这将工作

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

在你的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); 

如果你想添加itemsMyFragment的工具栏,你mustonCreateView函数中添加这一行

  setHasOptionsMenu(true); 

这条线是重要的,如果你忘记它,android不会填充你的菜单项。

假设我们在menu/fragment_menu.xml标识它们

之后,覆盖以下function

 @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; } 

希望这可以帮助

作为Pierre-Antoine LaFayette答案的最新答案

ActionBarActivity已弃用; 改用AppCompatActivity

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