来自Fragment ActionBarCompat内部的getSupportActionBar

时间:2013-08-19 18:36:49

标签: android android-fragments android-support-library android-actionbar-compat

我正在开始一个使用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

          //...
    }

使用它的Google页面(http://android-developers.blogspot.in/2013/08/actionbarcompat-and-io-2013-app-source.html)表示v4片段不应有任何更改。我是否需要将getActivity()所有来电投放到ActionBarActivity?这看起来很糟糕。

7 个答案:

答案 0 :(得分:263)

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

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

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

你需要演员。它的设计并不差,它具有向后兼容性。

答案 1 :(得分:35)

虽然这个问题已经得到了接受,但我必须指出这并不完全正确:从getSupportActionBar()调用Fragment.onAttach()会在活动轮换时产生NullPointerException

简答:

((ActionBarActivity)getActivity()).getSupportActionBar() (或其生命周期中的任何后续点)中使用onActivityCreated()代替onAttach()

答案很长:

原因是如果在轮换后重新创建ActionBarActivity,它将在实际创建ActionBar对象之前恢复所有碎片

ActionBarActivity库中support-v7的源代码:

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

答案 2 :(得分:29)

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

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

答案 3 :(得分: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添加到MyFragment内的工具栏中 您mustonCreateView函数

中添加此行
        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;
}

希望这会有所帮助

答案 4 :(得分:3)

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

不推荐使用ActionBarActivity;使用AppCompatActivity代替

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

答案 5 :(得分:0)

对于那些使用kotlin的人,

(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)

答案 6 :(得分:0)

作为 GzDev 答案的附录,如果您已经有了字符串,则可以使用 kotlin 的自动设置器:

(activity as AppCompatActivity).supportActionBar?.subtitle = my_string

您只需使用一个空字符串即可将其关闭。

请注意,这适用于 titlesubtitle