Fragment
后台堆叠,以便在一个活动中向后遍历一堆片段不会将操作栏恢复到之前片段中的原始状态。
事实证明,Action Bar实际上是附加到Activity本身,而不是片段!请记住,片段只是 UI 的模块位,并且必须明确指定对其他片段,活动部分甚至操作栏的控制。
继续阅读解决方案......
答案 0 :(得分:1)
我发现解决这个问题的最佳方法是通过Reto Meier answer对前一个问题的描述。我的解决方案将更深入地扩展他的答案。
我们想要建立的是,每次切换到不同的片段时我们都不想重新创建操作栏,原因是它效率不高。我将引导您完成我为学生安排应用程序编写的内容。它不是很复杂,它的入职经验是由活动中的多个片段组成的。
为了完成这项工作,我们需要确保使用 replace()
来切换片段。这比将片段叠加在一起更好,因为它允许您为每个片段单独配置操作栏。
第一块代码来自活动的内部类 LoginOptionsFragment
,其 onCreateView()
方法。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_login_options, container, false);
//LoginOptionsFragment will have its own action bar
setHasOptionsMenu(true);
//inject views. e.g: Button add_course
ButterKnife.inject(this, rootView);
add_course.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getFragmentManager().beginTransaction()
//exchange fragments. no messy clean-up necessary.
.replace(R.id.container, new AddCourseFragment())
.addToBackStack(null)
.commit();
}
});
return rootView;
}
在此,我不仅要确保通过 onCreateOptionsMenu()
致电 setHasOptionsMenu(true)
,而且主要是“ADD COURSE”单击按钮切换到 AddCourseFragment
,新片段将旧片段替换为活动的主要子片段。接下来,在我们覆盖onCreateOptionsMenu()
之后,我们来到onResume()
,但我们稍后会讨论这个问题;)
其次,我们到达AddCourseFragment
,我们甚至为操作栏填充自定义完成取消视图。那么让我们来看看代码!
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// BEGIN_INCLUDE (inflate_set_custom_view)
// Inflate a "Done/Cancel" custom action bar view.
final ActionBar actionBar = getActivity().getActionBar();
inflater = (LayoutInflater) actionBar.getThemedContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
//inflate custom action bar view
View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_cancel, null);
//set listeners to items in the view
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// "Done"
//remove custom view from action bar
actionBar.setDisplayShowCustomEnabled(false);
getFragmentManager().popBackStack();
//add course to list
}
});
customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// "Cancel"
//remove custom view from action bar
actionBar.setDisplayShowCustomEnabled(false);
getFragmentManager().popBackStack();
}
});
// Show the custom action bar view and hide the normal Home icon and title.
actionBar.setDisplayOptions(
ActionBar.DISPLAY_SHOW_CUSTOM,
ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME
| ActionBar.DISPLAY_SHOW_TITLE);
actionBar.setCustomView(customActionBarView,
new ActionBar.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayHomeAsUpEnabled(false);
// END_INCLUDE (inflate_set_custom_view)
View rootView = inflater.inflate(R.layout.fragment_add_course, container, false);
ButterKnife.inject(this, rootView);
return rootView;
}
您需要注意的仅部分是 DONE 和中添加的 OnClickListener
> CANCEL 按钮。在这里,我使用我之前对父Activity
的操作栏的引用,并告诉它停止显示自定义视图。现在除了这个特定方法之外,还有更多setDisplayXEnabled()
方法可以传入false。之后,我弹出backstack来获取前一个片段。
这是怎么回事。还记得我们onResume()
中挂出的 LoginOptionsFragment
方法吗?好吧,一旦片段从后台堆栈重新聚焦,就会调用onResume()
!因此,如果我们覆盖它并重新启用我们想要的操作栏的各个部分,我们就赢了吧?是的我们做到了。以下是您需要添加到onResume()
。
@Override
public void onResume() {
super.onResume();
ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayShowHomeEnabled(true); //show Home icon
actionBar.setDisplayShowTitleEnabled(true); //show title
// actionBar.setDisplayUseLogoEnabled(true); <--- more options
// actionBar.setDisplayHomeAsUpEnabled(true); <--- more options
}
我们在没有重新创建操作栏的情况下完成了所有操作。这是它的外观!
感谢阅读和快乐编码!