したがって、私のメイン アクティビティには 2 つのフラグメントが含まれます。activity_main.xml レイアウト ファイルには、1 つの (リスト) フラグメントと、2 番目のフラグメントのコンテナーとして機能するフレーム レイアウトがあります。
リスト フラグメント リスト ビューでアイテムがクリックされるたびに、クリックされたアイテムに対応する詳細が、フレーム レイアウトに含まれる 2 番目のフラグメントに表示されます。
それは結構です、それはうまくいきます。しかし、フラグメント トランザクション参照を使用して backStack を作成すると、backStack が期待どおりに動作しません。
私が期待したこと:
1) ユーザーがリスト ビューでアイテムをクリックすると、itemClicked に対応する詳細が 2 番目のフラグメント (フレーム レイアウト内) に表示されます。
2) ユーザーがリスト ビューで別のアイテムをクリックすると、そのアイテムに対応する詳細が、前のクリックに対応する詳細に置き換わります。
3) ユーザーが [戻る] ボタンをクリックすると、リスト ビューで前にクリックしたアイテムが、2 番目のフラグメント内のそのアイテムに対応する詳細と共に表示されます。
実際に発生すること:
上記のステップ 1 と 2 を繰り返します。ただし、ステップ 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
}
}
データを含むワークアウト クラス:
public class ワークアウト {
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;
}
}