问题
I am using the following code to populate my UI with 2 fragments, the containers are FrameLayout
's defined in XML. This first time this code is called i.e. when the app starts, it works fine, and both my fragments are displayed as expected. However after a configuration change(specifically, orientation), only the first fragment in the transaction is shown.
I don't think it's an issue with the fragments themselves, because if I reverse the code so one replace is called before the other or vice versa, that fragment will be displayed. So for example with the snippet from below as a guide, if I swap the mSummary and mDetails replace calls, then mDetails will be displayed and mSummary won't.
It's always the second one in the block that is missing.
// Using tablet layout
} else {
FragmentManager fm = super.getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.summary_container, mSummaryFragment);
ft.replace(R.id.details_container, mDetailsFragment);
ft.commit();
}
I'm saving the fragments in onSaveInstanceState
and restoring them from the Bundle savedInstanceState
when the activity is recreated. I also tried breaking the transaction into two pieces by calling commit()
and then getting another FragmentTransaction
object but no joy there.
回答1:
So for anyone coming across this at a later stage...
I finally manage to fix this by creating a new instance of the fragment and restoring it's state using a Fragment.SavedState
object. So:
if (mSummaryFragment.isAdded() && mDetailsFragment.isAdded()) {
Fragment.SavedState sumState = getSupportFragmentManager().saveFragmentInstanceState(mSummaryFragment);
Fragment.SavedState detState = getSupportFragmentManager().saveFragmentInstanceState(mDetailsFragment);
mSummaryFragment = new SummaryFragment();
mSummaryFragment.setInitialSavedState(sumState);
mDetailsFragment = new DetailsFragment();
mDetailsFragment.setInitialSavedState(detState);
}
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.add(R.id.summary_container, mSummaryFragment);
ft.add(R.id.details_container, mDetailsFragment);
ft.commit();
I do not understand why this works and the old method doesn't, however this may be helpful for someone else.
回答2:
Try using android:configChanges="orientation|keyboardHidden|screenSize"
in android-manifest
Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion
and targetSdkVersion
attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must decalare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).
Source : Documentation
Hence, also add "|screenSize" to configChanges
if your application targets API 13 and above
回答3:
this should work and orientation change will not affect the fragment., if you face any problem just let me know.
public class MainActivity extends FragmentActivity {
Fragment fragment = new Fragment1();
Fragment fragment2=new Fragment2();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = super.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.frame1, fragment);
ft.replace(R.id.frame2, fragment2);
ft.commit();
}
public void onSaveInstanceState(Bundle outState){
getSupportFragmentManager().putFragment(outState,"fragment1",fragment);
getSupportFragmentManager().putFragment(outState,"fragment2",fragment2);
}
public void onRetoreInstanceState(Bundle inState){
fragment = getSupportFragmentManager().getFragment(inState,"fragment1");
fragment2 = getSupportFragmentManager().getFragment(inState,"fragment2");
}
class Fragment1 extends Fragment{
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
ListView listView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.summary_view,container,false);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
class Fragment2 extends Fragment{
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
ListView listView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.detail_view,container,false);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
}
来源:https://stackoverflow.com/questions/18708357/multiple-calls-to-fragmenttransaction-replace-only-one-works-after-orientati