我有一个具有主/详细布局的应用程序(1 个活动、1 个 ListView 片段和 1 个详细片段)。当用户单击 ListView 中的项目时,片段事务会在右侧窗格中实例化一个详细片段,其中包括与该项目对应的信息。当显示细节片段时,我隐藏了初始操作栏按钮/项目并显示 3 个新的 AB 项目(完成/删除/取消)。用户可以通过按下后退按钮或按下 3 个 AB 项之一来清理右窗格并返回到初始 UI 状态。
我遇到的问题是,当用户选择应用程序的主页图标(即“向上导航”)时,活动会重新加载(即指示活动正在启动的动画可以被视为操作栏和UI 已重绘)。该问题仅在按下应用程序主页图标时发生。如果用户按下后退按钮或取消/完成/删除操作栏按钮,片段会简单地从右窗格中删除,并且 UI 会返回初始状态而无需任何“重新加载”。
活动的 XML 布局如下(在 LinearLayout 内;美化隐藏了该行):
<fragment class="*.*.*.ListFragment"
android:id="@+id/titles" android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<FrameLayout android:id="@+id/details" android:layout_weight="2"
android:layout_width="0px"
android:layout_height="match_parent" />
DetailsFragement 在其 onCreate 方法中有 actionBar.setDisplayHomeAsUpEnabled 语句:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
ActionBar actionBar = getSherlockActivity().getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
对于 ListView 片段和 Detail 片段,onCreateOptionsMenu() 和 onOptionsItemSelected() 方法都在片段中实现。在详细信息片段的代码下方:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.edit_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// some variable statements...
switch (item.getItemId()) {
case android.R.id.home:
//Toast.makeText(getSherlockActivity(), "Tapped home", Toast.LENGTH_SHORT).show();
onHomeSelectedListener.onHomeSelected();
return true;
case R.id.menu_edit_item_done:
editedTask.setTitle(editedTaskTitle);
onTaskEditedListener.onTaskEdited(editedTask, UPDATE_TASK, true);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
在主机活动中,我实现了 onHomeSelectedListner 来处理应用主页图标按下(即“向上导航”:
public void onHomeSelected(){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
TaskFragment taskFragment = (TaskFragment)getSupportFragmentManager().findFragmentById(R.id.details);
ft.remove(taskFragment);
ft.commit();
manager.popBackStack();
}
负责处理所有其他操作栏按钮(即完成/删除/取消)的活动侦听器是 onTaskEditedListener,除了处理某些数据的其他代码之外,它具有与上面所示相同的片段事务。
更新(1/24) 根据 tyczj 和 straya 的反馈,我在活动的 onCreate()、onResume()、onPause() 中放置了日志语句,以确定 onHomeSelected 和 onTaskEdited 侦听器之间的差异。我可以确认在“向上导航”事件(即 onHomeSelected)期间调用了 onPause()、onCreate() 和 onResume()。而在 onTaskEdited 调用期间(即后退按钮或完成/删除/取消按下)没有调用这些事件。
更新 (1/25) 根据 Mark Murphy 的建议,我在“case android.R.id.home”语句中注释掉了 onHomeSelected 方法调用,只是为了看看 Activity 会做什么。当时的想法是,应用程序不会做任何事情,因为 are no 语句。事实证明并非如此。即使没有调用侦听器方法(即删除片段),活动也会重新启动,并且从片段容器中删除详细片段。
更新 (2/28) 我暂时解决了我的主要活动通过禁用窗口动画重新启动的事实(如我自己的答案中突出显示的那样)。然而,通过进一步的测试,我发现了一个错误。感谢 Wolfram Rittmeyer 的示例代码,我能够找出我的活动在向上导航期间重新启动(在主/详细单一布局中)的真正原因:1)虽然我使用这个“onHomeSelectedListener”来正确删除片段从后台堆栈中,我仍然在 ListView 片段的 onOptionsItemSelected 中有一些残余代码,这些代码正在创建一个新的意图来启动托管活动。这就是为什么按下应用程序的主页图标会重新启动活动。2)在我的最终实现中(如我自己的答案所示),