Подтвердить что ты не робот

Как управлять состоянием пользовательского интерфейса и задним стеком в макете с одним/двумя панелями

У меня возникли проблемы, обертывая голову тем, как правильно управлять Fragment в типичном шаблоне шаблона списка.

Мой макет отлично работает и структурирован так для пейзажного вида (двойная панель):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ... >
    <FrameLayout android:id="@+id/list" ... />
    <FrameLayout android:id="@+id/container" ... />
</LinearLayout>

И как это для портретного вида (одно окно):

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/container" ... />

У меня также есть refs.xml в res/values-w600dp/, чтобы убедиться, что соответствующий макет загружен на основе ширины экрана устройства.

Когда элемент списка выбран, в альбомном представлении должен отображаться список и детали бок о бок, в то время как портретный портрет должен показывать только полноэкранный режим. Когда ничего не было выбрано, в альбомном представлении должны быть слева слева и пустое пространство справа, а портретный вид должен показывать только полный список в списке.

example

Однако здесь, где у меня возникают проблемы:

  • Я использую "основной" Activity для списка + дополнительный макет детали и еще одну "информацию" Activity для портрета, только для макета? Это похоже на то, что делает Fragments guide. Я получил этот подход для работы в целом, но как мне сохранить состояние фрагмента моих деталей при изменении ориентации?

    Рассмотрим обратный пример, показанный выше - поворот с портрета на пейзаж, пока детали видны, значит, детали Activity должны быть finish() ed, поэтому основной Activity может отображать двухпанельный макет, но это также разрушает фрагмент деталей и его savedInstanceState. Если пользователь набрал информацию в поля EditText в фрагменте детали, затем поворачивает устройство, как мне сохранить все состояние пользовательского интерфейса фрагмента детали, когда я добавляю его на основную (двухпанельную) Activity?

  • Я использую только один Activity и сам управляю Fragment? Это позволяет мне сохранять состояние пользовательского интерфейса деталей, когда меняется ориентация (поскольку Android позаботится об этом автоматически), но он становится беспорядочным, когда дело доходит до заднего стека.

    Рассмотрим случай на изображении - поворот от пейзажа к портрету, когда детали будут видны, должен показать отображение деталей с одной панелью, но как правильно управлять задним стеком и ActionBar домашним значком, чтобы отобразить список одиночный -pane? Поворот назад к пейзажу также должен был бы отменить все предыдущие операции со стеклом, так как оба фрагмента будут видны сразу.

После нескольких поисков я нашел два похожих вопроса (Переключение с двойной панели на одиночную панель смены ориентации, поддерживающей фрагмент фрагмента и Сохранять состояние фрагмента между действиями), но моя ситуация немного отличается, потому что я не пытаюсь модифицировать эту функциональность, но лучше всего планирую ее. Что мне не хватает? Разумеется, Android может управлять как задним стеком (как в случае с несколькими Activity) , так и состоянием пользовательского интерфейса (как в случае с одним случаем Activity) сразу?

4b9b3361

Ответ 1

Я решил это, перейдя по нескольким маршрутам действий. См. мой ответ на "Сохранять состояние фрагментации между действиями" .

Ключ использовал FragmentManager.saveFragmentInstanceState(), чтобы сохранить состояние интерфейса фрагмента и Fragment.setInitialSavedState(), чтобы восстановить его при создании экземпляра того же фрагмента в другой активности.

В моих целях я обнаружил, что мне нужно сохранить состояние пользовательского интерфейса в двух случаях. Я создал вспомогательный метод public void saveState() внутри моего фрагмента и вызвал его из собственного метода onPause(), а также из моего "основного" действия непосредственно перед использованием replace(), чтобы прикрепить новый экземпляр фрагмента к двойному объекту, панели.

Мне все еще интересно узнать, нужна ли манипуляция обратным стеком для этого типа сценария однократной/двойной панели или если для подхода с одной активностью потребуется переопределить onBackPressed и имитировать задний стек вручную.

Ответ 2

Можно использовать только одно действие, но вам придется управлять стоп-кадрами, когда вы находитесь в портретной ориентации.

Как вы описываете поведение приложения, могут быть 4 состояния:

  • Состояние A: портрет, показывающий фрагмент списка.
  • Состояние B: портрет, показывающий фрагмент детали с фрагментом списка в стеке задней части.
  • Состояние C: пейзаж, показывающий фрагмент списка слева и пустое пространство справа.
  • Состояние D: пейзаж, показывающий как фрагмент списка, так и фрагмент деталей рядом.

Представьте, что вы находитесь в состоянии D (оба фрагмента, позвоните им FA и FB), и вы измените ориентацию телефона. Следующее состояние должно быть состоянием B, но проблема заключается в том, что ваш портретный макет имеет только один FrameLayout. Используя следующее как макет одиночной панели:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/list" ... />

Android воссоздает FA и привяжет его к этому FrameLayout. FB, с другой стороны, также будет воссоздан, но не будет связан контейнер, поэтому он не появится. На этом этапе вы можете создать другой фрагмент FB2 с тем же содержимым, что и FB, и использовать его для замены FA. У вас будет FA-FB2 в вашей задней части и FB.

Если вы снова измените ориентацию (ожидая состояния D), вы можете использовать onSaveInstanceState(), чтобы вытащить FB2 из задней части с помощью popBackStack(), тем самым снова используя FA и FB. Перед удалением FB2 вы также можете скопировать его содержимое в FB. Когда приложение снова находится в состоянии D, FB будет иметь свой FrameLayout.

Было бы еще несколько переходов и ситуаций, которые вам нужно было бы позаботиться, но основная идея была бы в том, чтобы это было.

Это не очень изящное решение, поэтому я уверен, что он должен быть лучше, а может быть, более эффективным (без повторения фрагментов, например), чтобы решить эту проблему.