Несколько вызовов 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);
            }

        }

}
Другие вопросы по тегам