Фрагмент без просмотра сбоев при изменении конфигурации
У меня есть пользовательский интерфейс, где мне нужен Fragment
для отображения (с видом) в альбомном режиме, но не в портретном режиме. В портретном режиме он все равно будет доступен, но вместо этого отобразит его результат с помощью ListPopupWindow
.
Я решил, что смогу справиться с этим, используя тег <fragment />
для макета ландшафта, создавая фрагмент программно, если он не был запущен (в случае, когда мы находимся на портрете).
Это работает отлично, пока вы начинаете в ландшафте, если вы начинаете с портрета, где фрагмент создается программно, ваше приложение будет сбой при повороте эмулятора, когда он попытается прикрепить фрагмент к вашему макету:
java.lang.IllegalStateException: Фрагмент не создал вид. в android.app.Activity.onCreateView(Activity.java:4095)
Документы для Fragment.isInLayout()
, похоже, намекают, что он должен иметь возможность обрабатывать его следующим образом:
Возвращает true, если макет включен как часть иерархии видов деятельности через тег. Это будет всегда быть правдой, когда фрагменты созданный с помощью тега, за исключением случая, когда фрагмент восстанавливается из предыдущего и он не появляется в компоновка текущего состояния.
Итак, вопрос в том, как это сделать правильно или если что-то мне не хватает?
UPDATE:
Кажется, что isInLayout()
не ведет себя так же хорошо, как сейчас. Он возвращает false, если вы добавили Fragment
в контейнер вручную.
Кроме того, если вы добавите Fragment
вручную в контейнер и затем поверните (устройство) в макет, который не содержит этот макет, он сработает:
Вызвано: java.lang.IllegalArgumentException: Нет просмотр найден для id 0x7f060011 для фрагмент SearchFragment {4042f868 # 2 id = 0x7f060011 SearchFragment} at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:722)
Ответы
Ответ 1
Есть ли у вас ответ на этот вопрос? У меня была аналогичная проблема, и мне удалось найти решение. Вы можете легко сделать то, что вы пытаетесь сделать следующим образом:
Создайте два разных макета один в каталоге макета, один в каталоге макета-земли. Один в каталоге макета-земля будет использоваться в ландшафтном режиме. В качестве заполнителя, в котором вы хотите, чтобы ваш фрагмент был включен, используйте элемент s FrameLayout и укажите его, например, с идентификатором "my_fragment". Макет в каталоге макета не должен содержать ни одного элемента с этим идентификатором.
В методе onCreate используйте findViewById (R.id.my_fragment), чтобы найти место для фрагмента. Если он существует, вы находитесь в ландшафтном режиме и должны добавить свой фрагмент (если он еще не существует): add (R.id.my_fragment, new MyFragment, "myFragment" ). Если вы получите нуль, вы находитесь в портретном режиме и должны не создавать фрагмент.
Будьте очень осторожны, чтобы вы никогда не заменяли фрагмент, созданный с помощью тега, тем, который вы динамически создаете в своей программе. Фрагмент, для которого isInLayout возвращает true, - это совершенно другой зверь, тот, для которого он возвращает false. Их жизненные циклы совершенно разные. Замена одного на другого приведет к ужасному исключению IllegalStateException. Проблема "Фрагмент не создавал представление".
-blake
Ответ 2
Ваша проблема также может быть связана с отсутствием макета lanscape для используемого фрагмента. У вас может быть один для портрета, и поэтому ваша программа работает нормально, но когда вы вращаете свое устройство, ОС, вероятно, ищет вид в альбомной папке и не находит вид, поэтому объявляет его отсутствующим. Убедитесь, что у вас есть просмотр как в папке "layout", так и "layout-land".