Android 从片段ActionBarCompat内部获取SupportActionBar
我正在启动一个新项目,它使用Android 从片段ActionBarCompat内部获取SupportActionBar,android,android-fragments,android-support-library,android-actionbar-compat,Android,Android Fragments,Android Support Library,Android Actionbar Compat,我正在启动一个新项目,它使用v7支持库中的AppCompat/ActionBarCompat。我试图找出如何在片段中使用getSupportActionBar。托管片段的活动扩展了ActionBarActivity,但我没有看到类似的片段支持类 从我的碎片里 public class CrimeFragment extends Fragment { //... getActivity().getSupportActionBar().setSubt
v7
支持库中的AppCompat/ActionBarCompat
。我试图找出如何在片段中使用getSupportActionBar
。托管片段的活动扩展了ActionBarActivity
,但我没有看到类似的片段支持类
从我的碎片里
public class CrimeFragment extends Fragment {
//...
getActivity().getSupportActionBar().setSubtitle(R.string.subtitle); // getSupportActionBar is not defined in the v4 version of Fragment
//...
}
使用它的谷歌页面()说,
v4
片段应该没有变化。我是否需要将所有getActivity()
调用强制转换为ActionBarActivity
?这似乎是一个糟糕的设计。在片段之后。onActivityCreated(…)您将拥有一个可通过getActivity()访问的有效活动
您需要将其强制转换为ActionBarActivity,然后调用getSupportActionBar()
你确实需要演员。这不是糟糕的设计,而是向后兼容性。虽然这个问题已经有了公认的答案,但我必须指出,它并不完全正确:从
Fragment.onAttach()
调用getSupportActionBar()
将在活动旋转时导致NullPointerException
简短回答:
在ActivityCreated()上的中使用((ActionBarActivity)getActivity()).getSupportActionBar()
(或其生命周期中的任何点),而不是onAttach()
长答案:
原因是,如果在旋转后重新创建ActionBar活动
,它将在实际创建ActionBar
对象之前恢复所有片段
support-v7
库中的ActionBarActivity
源代码:
@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()
,它从窗口样式中读取mhaActionBar
变量
- 在
mhaActionBar
为true之前,getSupportActionBar()
将始终返回null
ActionBarActivityDelegate.getSupportActionBar()的源代码
:
如果有人使用com.android.support:appcompat-v7:和AppCompatActivity作为活动,那么这将起作用
((AppCompatActivity)getActivity()).getSupportActionBar().setSubtitle(R.string.subtitle);
在fragment.xml
中,从支持库添加工具栏
标记
<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
函数中
setHasOptionsMenu(true);
这一行很重要,如果您忘记了它,android将不会填充您的菜单项
假设我们在menu/fragment\u 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;
}
希望这对皮埃尔·安托万·拉法叶的回答有所帮助
ActionBarActivity已被弃用;改用AppCompatActivity
((AppCompatActivity)getActivity()).getSupportActionBar();
对于使用kotlin的用户
(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)
作为GzDev答案的补充,如果您已经拥有字符串,则可以使用kotlin的自动设置器:
(活动作为AppCompatActivity)。supportActionBar?.subtitle=my_字符串
只需使用一个空字符串就可以将其关闭
请注意,这适用于标题和副标题。谢谢。我希望这不是答案。我希望getActionBar()可能会返回一个v7 ActionBar,如果我需要额外的功能,我会使用它。现在,我的片段必须知道它们承载在什么类型的活动中。不,这不是因为getActionBar()是一个活动API,它不存在于旧版本的SDK(pre-Honeycom)上。这就是为什么我们需要支持类来反映最新SDK中新的和改进的类和API的功能。@Pierre Antoinalafayette为什么必须在onAttach()中实现这一点?在onActivityCreated()中不是更好吗?是的,因为对getSupportActionBar()的第一次调用将通过查找活动中的视图来初始化ActionBar,所以在onActivityCreated()中进行此调用可能更好。我只是想指出,您需要等待片段有活动。我将更新答案。不推荐使用AppCompatActivity而不是ActionBarActivityActionBarActivity
。使用appcompativity
代替onActivityCreated
现在也不推荐使用(有关替代方法,请参阅)。
@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;
}
((AppCompatActivity)getActivity()).getSupportActionBar();
(activity as AppCompatActivity).supportActionBar.setSubtitle(R.string.subtitle)