从片段ActionBarCompat内部获取getSupportActionBar


102

我正在启动一个使用AppCompat/ActionBarCompatin v7支持库的新项目。我试图弄清楚如何getSupportActionBar在片段中使用from。我托管片段的活动可以扩展ActionBarActivity,但是我没有看到类似的Fragments支持类。

从我的片段中

    public class CrimeFragment extends Fragment {
          //...

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

          //...
    }

使用它的Google页面(http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html)表示,该v4片段应该没有变化。我是否需要将所有getActivity()呼叫投射到ActionBarActivity?这似乎是糟糕的设计。

Answers:


287

Fragment.onActivityCreated(...)之后,您将具有可通过getActivity()访问的有效活动。

您需要将其强制转换为ActionBarActivity,然后调用getSupportActionBar()。

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

您确实需要演员表。这不是糟糕的设计,而是向后兼容。


3
谢谢。我希望这不会是答案。我希望getActionBar()会返回一个v7 ActionBar,如果需要额外的功能,我可以将该v7投给它。现在,我的片段必须知道它们所托管的活动类型
Paul

不,这不是因为getActionBar()是一个活动API,在旧版本的SDK(蜂窝前)上不存在。这就是为什么我们需要支持类来反映最新SDK中新的和改进的类以及API的功能。
皮埃尔·安东尼·拉斐特

@ Pierre-AntoineLaFayette为什么必须在onAttach()中完成此操作?在onActivityCreated()中会更好吗?
IgorGanapolsky 2014年

是的,因为第一次调用getSupportActionBar()会通过在活动中查找视图来初始化ActionBar,因此最好在onActivityCreated()中进行此调用。我只是试图表明您需要等到片段活动为止。我将更新答案。
皮埃尔·安托万·拉斐特

2
使用AppCompatActivity而不是ActionBarActivity
Aparajita Sinha

37

尽管这个问题已经有了一个可以接受的答案,但我必须指出,这并不完全正确:轮换活动时,调用getSupportActionBar()from Fragment.onAttach()会导致错误NullPointerException

简短答案:

使用((ActionBarActivity)getActivity()).getSupportActionBar()onActivityCreated()(或任何在它的生命周期之后点)代替onAttach()

长答案:

原因是,如果ActionBarActivity在轮换后重新创建an ,它将实际创建ActionBar对象之前还原所有Fragments 。

ActionBarActivity中的源代码support-v7

@Override
protected void onCreate(Bundle savedInstanceState) {
    mImpl = ActionBarActivityDelegate.createDelegate(this);
    super.onCreate(savedInstanceState);
    mImpl.onCreate(savedInstanceState);
}
  • ActionBarActivityDelegate.createDelegate()mImpl根据Android版本创建对象。
  • 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;
}

2
ActionBarActivity不推荐使用。使用AppCompatActivity替代
萨满Sattari

29

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

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

5

在支持库的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);

如果要添加items到工具栏中,MyFragmentmustonCreateView函数内添加此行

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

希望这可以帮助



3

对于那些使用kotlin的人,

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.