所以我的主要活动包含两个片段。在activity_main.xml 布局文件中,我有一个(列表)片段,然后是一个框架布局,它将充当第二个片段的容器。
每次在列表片段列表视图上单击项目时,与单击的项目对应的详细信息应显示在框架布局中包含的第二个片段中。
没关系,这行得通。但是,当我使用片段事务引用创建 backStack 时,backStack 无法按预期工作。
我的期望:
1) 用户在列表视图中单击一个项目,与 itemClicked 对应的详细信息将显示在第二个片段上(在框架布局中)。
2) 用户点击列表视图中的另一个项目,该项目对应的详细信息将替换之前单击对应的详细信息。
3) 用户单击后退按钮,在列表视图中单击的上一个项目将与第二个片段中该项目对应的详细信息一起显示。
实际发生的情况:
我重复上面的步骤一和二。但是在第 3 步中,应用程序退出,因为在调用 onStop 方法后调用 onDestroy 方法。
这是主要活动。
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity implements WorkoutListFragment.WorkoutListListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void itemClicked(long id) {
WorkoutDetailFragment details = new WorkoutDetailFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
details.setWorkout(id);
ft.replace(R.id.fragment_container, details);
ft.addToBackStack(null);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
编辑:
(用户需要 LOGCAT):
08-27 22:18:10.850 12699-12699/? I/art﹕ Not late-enabling -Xcheck:jni (already on)
08-27 22:18:11.088 12699-12716/ramansb.workout D/OpenGLRenderer﹕ Use EGL_SWAP_BEHAVIOR_PRESERVED: true
08-27 22:18:11.092 12699-12699/ramansb.workout D/﹕ HostConnection::get() New Host Connection established 0xb3ee7f00, tid 12699
08-27 22:18:11.106 12699-12699/ramansb.workout D/Atlas﹕ Validating map...
08-27 22:18:11.169 12699-12716/ramansb.workout D/﹕ HostConnection::get() New Host Connection established 0xb3fef0a0, tid 12716
08-27 22:18:11.186 12699-12716/ramansb.workout I/OpenGLRenderer﹕ Initialized EGL, version 1.4
08-27 22:18:11.192 12699-12716/ramansb.workout D/OpenGLRenderer﹕ Enabling debug mode 0
08-27 22:18:11.217 12699-12716/ramansb.workout W/EGL_emulation﹕ eglSurfaceAttrib not implemented
08-27 22:18:11.217 12699-12716/ramansb.workout W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xb3fe5080, error=EGL_SUCCESS
编辑:
锻炼细节片段:
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class WorkoutDetailFragment extends Fragment {
//All fragments require an empty constructor ( no args )
public WorkoutDetailFragment(){}
private long workoutId;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(savedInstanceState != null){
workoutId = savedInstanceState.getLong("workoutId");
}
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_workout_detail, container, false);
}
public void onStart() {
super.onStart();
View view = getView(); //gets Fragment's root view, gets activity class name
if (view != null) {
TextView title = (TextView) view.findViewById(R.id.textTitle);
Workout workout = Workout.workouts[(int) workoutId];
title.setText(workout.getName());
TextView description = (TextView) view.findViewById(R.id.textDescription);
description.setText(workout.getDescription());
}
}
public void setWorkout(long id){
this.workoutId = id;
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putLong("workoutId", workoutId);
}
}
锻炼清单片段:
import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
/**
* A simple {@link Fragment} subclass.
*/
//Extends ListFragment as the fragment is a list fragment
public class WorkoutListFragment extends ListFragment{
interface WorkoutListListener{
void itemClicked(long id);
}
private WorkoutListListener listener;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//The activity has implemented the WorkoutListListener interface therefore it can be casted to a type of WorkoutListListner
this.listener = (WorkoutListListener) activity;
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
if(listener != null){
listener.itemClicked(id);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Creating array of workout names
String[] names = new String[Workout.workouts.length];
for(int i=0; i<names.length; i++){
names[i] = Workout.workouts[i].getName();
}
//Creating ArrayAdapter, such that the ListView(Subclass of adapter view) can use data from a java Array.
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(inflater.getContext(), android.R.layout.simple_list_item_1,
names);
setListAdapter(listAdapter);
return super.onCreateView(inflater, container, savedInstanceState);
//Calling the super class returns the default layout for ListFragments
}
}
包含数据的锻炼课程:
公共课锻炼{
private String name;
private String description;
public static final Workout[] workouts = {
new Workout("The Limb Loosener", "5 Handstand push-ups\n10 1-legged squats\n15 Pull-ups"),
new Workout("Core Agony", "100 Pull-ups\n100 Push-ups\n100 Sit-ups\n100 Squats"),
new Workout("The Wimp Special", "5 Pull-ups\n10 Push-ups\n15 Squats"),
new Workout("Strength and Length", "500 meter run\n21 x 1.5 pood kettleball swing \n21 x pull-ups")
};
//Each Workout has a name and description
private Workout(String name, String description){
this.name = name;
this.description = description;
}
public String getDescription(){
return description;
}
public String getName(){
return name;
}
public String toString(){
return this.name;
}
}