Несколько вызовов FragmentTransaction.replace() - только один работает после изменения ориентации
Я использую следующий код, чтобы заполнить мой интерфейс с 2 фрагментами, контейнеры FrameLayout
определено в XML. Это первый раз, когда вызывается этот код, т.е. когда приложение запускается, оно работает нормально, и оба моих фрагмента отображаются, как и ожидалось. Однако после изменения конфигурации (в частности, ориентации) отображается только первый фрагмент в транзакции.
Я не думаю, что это проблема самих фрагментов, потому что если я переверну код, чтобы одна замена вызывалась раньше другой или наоборот, этот фрагмент будет отображаться. Так, например, с помощью фрагмента снизу в качестве руководства, если я поменяю местами вызовы mSummary и mDetails, то будут отображаться mDetails, а mSummary - нет.
Это всегда второй в блоке, который отсутствует.
// 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();
}
Я сохраняю фрагменты в onSaveInstanceState
и восстановление их из Bundle savedInstanceState
когда деятельность воссоздается. Я также попытался разбить транзакцию на две части, позвонив commit()
а затем получить другой FragmentTransaction
объект, но нет радости там.
3 ответа
Так что для тех, кто сталкивается с этим на более позднем этапе...
Наконец-то мне удалось это исправить, создав новый экземпляр фрагмента и восстановив его состояние с помощью Fragment.SavedState
объект. Так:
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();
Я не понимаю, почему это работает, а старый метод - нет, однако это может быть полезно для кого-то еще.
Попробуйте использовать android:configChanges="orientation|keyboardHidden|screenSize"
в android-manifest
Внимание! Начиная с Android 3.2 (уровень API 13), "размер экрана" также изменяется, когда устройство переключается между книжной и альбомной ориентацией. Таким образом, если вы хотите предотвратить перезапуск среды выполнения из-за изменения ориентации при разработке для API уровня 13 или выше (как объявлено minSdkVersion
а также targetSdkVersion
атрибуты), вы должны включить значение "screenSize" в дополнение к значению "direction". То есть вы должны decalare android: configChanges = "direction | screenSize". Однако, если ваше приложение предназначено для уровня API 12 или ниже, то ваша активность всегда сама обрабатывает это изменение конфигурации (это изменение конфигурации не перезапускает вашу активность, даже при работе на устройстве Android 3.2 или выше).
Источник: Документация
Следовательно, также добавьте "| screenSize" к configChanges
если ваше приложение предназначено для API 13 и выше
Это должно сработать, и изменение ориентации не повлияет на фрагмент. Если вы столкнулись с какой-либо проблемой, просто дайте мне знать.
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);
}
}
}