Intereting Posts
ActivityLifecycleCallbacks не запускаются, когда активность убивается с помощью «Не продолжать действия», Какова полезность третьего аргумента View.resolveSizeAndState ()? Почему материальное приложение работает медленнее, чем традиционное приложение, разработанное голографически Gson и Active Android: Попытка сериализации java.lang.Class. Забыл зарегистрировать адаптер типа? Не удается запустить android MediaPlayer onCompletion Отправить электронную почту программно в Android Wrap_content width на mutiline TextView Socket.io – ReferenceError: io не определен ListView не обновляется после фильтрации Задание зависимостей Maven в build.gradle не работает Как получить фрагмент, добавленный в XML-макет В чем разница между этим, getContext () и getActivity ()? Gradle – Android Studio строит слишком медленное приложение с несколькими приложениями Как изменить размер веб-представления android после добавления в него данных Android NumberPicker с Formatter не форматируется при первом рендеринге

Дизайн фрагмента: Адаптация к нескольким макетам экрана путем отображения / скрытия фрагментов в рамках одного действия?

Я пытаюсь понять, как использовать Фрагменты для создания приложений, которые хорошо адаптируются к нескольким экранам и макетам. Я изучил несколько примеров:

  1. Документ « Фрагменты» в руководстве для разработчиков Android.
  2. Приложение Google IO
  3. Образец фрагментов из ActionBar Sherlock .

Все они выступают за многоступенчатый подход:

  • На большом экране отобразите одно действие с несколькими Fragment s
  • На меньшем экране разделите Fragment s на несколько Activity s.

Я подумал о другом подходе – одном Activity :

  • Имейте одно действие со всеми Fragment s в нем.
  • В зависимости от размера и ориентации экрана покажите / скройте соответствующие Fragment (используя FragmentTransaction.show() / FragmentTransaction.hide() ).

Чтобы проиллюстрировать тот же «список статей / статей статьи», который использует руководство для разработчиков Android:

  • У вас есть News содержащие как ArticleListFragment и ArticleReaderFragment .
  • На вкладке всегда отображаются оба фрагмента.
  • На телефоне ArticleReaderFragment изначально скрыт. Когда статья выбрана из списка, ArticleListFragment скрыт, и показан ArticleListFragment .

Кто-нибудь использовал подобный подход? Существуют ли какие-либо практические недостатки, которые может иметь этот метод? Кажется ли это лучше / хуже по сравнению с многопользовательским способом? Например, фрагменты нельзя отображать / скрывать в XML – для этого нужно использовать FragmentTransaction .


EDIT 1: описание гипотетического сценария

Представьте приложение, которое может отображать до трех «панелей» за раз на экране. Кроме того, это факторы, которые следует учитывать:

  • Телефон может отображать только одну панель за раз (независимо от ориентации на портрете / альбомной ориентации)
  • 7-дюймовый планшет может отображать 2 панели, разбивать по вертикали в режиме «Портрет» и разделять по горизонтали в альбомном режиме.
  • Планшет на 10 дюймов может отображать 2 панели, разделенных вертикально в Portrait; 3 панели разделены горизонтально в ландшафте.

Для простоты, держите экраны телевизора вне обсуждения.

Теперь, переведя это в дизайн:

  • У нас есть три фрагмента: Frag1, Frag2 и Frag3.
  • В простейшем случае все три фрагмента находятся в одной активности (назовем ее ActivityA). Это 10-дюймовый ландшафтный корпус.
  • Другой «простой» случай – когда каждый фрагмент находится в своей собственной деятельности – ActivityA содержит Frag1; ActivityB содержит Frag2, а ActivityC содержит Frag3.

До сих пор мы не рассматривали ничего, что существенно отличается от примера News Reader, представленного в руководстве разработчика Android. Единственное существенное отличие состоит в том, что три фрагмента вместо двух.

Теперь, случай 7-дюймовых вкладок, которые могут вместить только 2 фрагмента. Как это будет работать? Обратите внимание, что возможны две комбинации:

  1. Отображаются Frag1 и Frag2.
  2. Отображаются Frag2 и Frag3.

Я просто не могу обмануть это. Я делаю все это в ActivityA? Я просто создаю совершенно новый ActivityD? Сколько макетов мне нужно создать (я подсчитал около 8)? Разве это не слишком много перестановок?

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

Любые предложения о том, как справиться с этим, не перегруженные макетами и комбинациями?

Solutions Collecting From Web of "Дизайн фрагмента: Адаптация к нескольким макетам экрана путем отображения / скрытия фрагментов в рамках одного действия?"

Этот ответ от @Taylor Clark был довольно информативным. Тем не менее, это не был фактический обмен опытом использования однозадачного подхода, как я спросил в моем первоначальном вопросе. Я решил изменить пример News Reader в руководстве разработчика Android, чтобы использовать однозадачный подход и придумал подходящее решение.

Что еще предстоит выяснить, каковы варианты использования, когда этот подход предпочтительнее по методу множественной активности (или вообще есть такие случаи). Кроме того, я не стал подробно останавливаться на 3-панельном сценарии, описанном в Редактировании 1 моего вопроса.

Я надеюсь опубликовать весь свой проект в ближайшее время, но вот краткий обзор того, как я это сделал:

  • Одиночная Activity : NewsActivity
  • Два фрагмента: TitlesListFragment и DetailsFragment
  • Оба фрагмента всегда присутствуют в NewsActivity . В зависимости от текущей двухпанели, я показываю / скрываю соответствующий фрагмент.

Некоторые проблемы, с которыми я столкнулся:

Назначение макета как двойного окна или нет:

В оригинальном примере News Reader в двухпанельных макетах есть FrameLayout для хранения новостей. Мы выясняем, находимся ли мы в настоящее время в двухпанельном макете, проверяя наличие этого макета кадра.

Однако в моем решении оба фрагмента всегда присутствуют во всех макетах. Я взломал это, включив View с id dualPane и android:visibility="gone" в те макеты, которые я хочу быть двойными, и опускаю это представление в однопанельном макете. Тогда это было вопросом

mDualPane = findViewById(R.id.dualPane)!=null;

РЕДАКТИРОВАТЬ:

Есть лучшие способы обозначить двойную структуру, чем наличие фиктивного представления. Я предпочитаю создавать булевский ресурс. Например, у меня есть config.xml следующим образом:

 <resources> <bool name="dual_pane">false</bool> </resources> 

Затем я могу разместить дополнительные файлы config.xml в папках, таких как values-xlarge-land , values-port или values-sw600dp т. Д. И настроить логическое значение на true или false как я желаю.

Затем в коде это вопрос getResources().getBoolean(R.bool.dual_pane);

Закрытие фрагмента детали

Это была проблема дифференциации закрытия Fragment закрытия Fragment . В конце концов, мне пришлось переопределить onBackPressed() следующим образом:

  • В режиме двойной панели просто вызовите super.onBackPressed() ;
  • В режиме с одной TitlesListFragment , если мы находимся в TitlesListFragment , вызовите super.onBackPressed() ;
  • В режиме с одной DetailsFragment , если мы находимся в DetailsFragment , рассмотрим его как закрытие фрагмента. Это означает, что он скрывает его и показывает TitlesListFragment .

Это не идеально, но это лучшее, что я мог бы придумать.

EDIT :

Основываясь на предложении @SherifelKhatib в комментариях, существует гораздо более чистый способ обработки нажатий на кнопки: просто добавьте в стопку фрагмента транзакцию отображения / скрытия фрагмента детали. Таким образом, когда вы нажимаете кнопку «Назад», транзакция фрагмента отменяется. Вы также можете вручную поместить стопку назад, если вы хотите сделать это при других нажатиях кнопок.

Обычно приложения разделяются на «Действия», потому что каждый представляет собой конкретную «вещь», которую пользователь может сделать. Например, в приложении электронной почты определенный набор действий может быть:

  1. Просмотр списка сообщений
  2. Просмотр информации о сообщении
  3. Составление ответа на письмо.

Каждое действие может быть его собственным действием, которое показывает один (или набор) фрагментов. Однако, если бы у вас была экранная недвижимость, было бы разумно объединить просмотр списка сообщений и деталь сообщения в одно действие, которое может показать / скрыть фрагмент «подробного представления». По сути, Фрагменты позволяют показывать пользователю несколько «действий» за один раз.

Что нужно учитывать при принятии решения:

  1. Фрагменты, указанные в xml, не могут быть предоставлены аргументами
  2. Если ваше решение основано на ориентации экрана, вы всегда можете использовать квалификаторы ресурсов, чтобы указать на другой макет с более / менее фрагментами (например, макет-земля-большой)
  3. Фрагменты не поддерживаются.
  4. Являются ли фрагменты работающими вместе, чтобы обеспечить пользователям оптимизированный опыт?
  5. Есть ли время, когда один из ваших фрагментов исчезнет навсегда? Если это так, возможно, пришло время для нового действия
  6. Иди со своей кишкой. Если его «естественное» для вас приложение для замены фрагментов, пойдите для него. Просто помните, что если вы обнаружите, что делаете это много, возможно, отдельное мероприятие является более подходящим решением

Я обычно использовал «подход с несколькими фрагментами» для планшетных версий приложений и «один фрагмент за активность» для телефонов, что звучит в соответствии с вашим первым подходом . Не то, чтобы у второго не было времени и места, но я видел, как реализация становится беспорядочной!

Извините за многословный ответ! Возможно, вы могли бы рассказать подробнее о своем конкретном случае использования? Надеюсь это поможет!

Ответ на вопрос «Редактировать один»


Вот как я могу представить ваш проект приложения:

Исходные файлы:

Yourapp.package.phone: NewsActivity1, NewsActivity2, NewsActivity3

Yourapp.package.tablet: NewsMultipaneActivity

Ресурсы

макет /

 activity_news.xml- phone version, only includes Fragment1 activity_news_detail.xml- phone version, only includes Fragment2 activity_news_<something>.xml- phone version, only includes Fragment3 

Макет-большой /

 activity_news.xml- 7" tablet version, includes Fragment2 and an empty fragment container. Split vertically 

макет большой участок /

 activity_news.xml- same as layout-large, but with the split being horizontally 

Макет-XLarge-земля /

 activity_news.xml- 10"+ tablet version, contains all three fragments split horizontally 

Так что здесь происходит?

  • Если ваше приложение работает на телефоне, запустите NewsActivity1
  • Если приложение запущено на планшете, запустите NewsMultipaneActivity

Android будет менять макеты для вас, исходя из размера экрана и ориентации, если имена файлов совпадают. Поскольку Fragment2 всегда будет отображаться, вы можете «жестко закодировать» его в планшетах планшетов. Затем вы можете использовать FragmentTransactions для переключения между Fragment1 и Fragment3 в контейнере по мере необходимости

Обязательно ознакомьтесь с http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources, чтобы узнать, как вы можете использовать квалификаторы ресурсов для смягчения некоторых головных болей разных экранов и ориентации

Благодарим вас за этот вопрос и ваши идеи. Я использовал многозадачный подход, пока не столкнулся с проблемой. Мое приложение похоже на читателя новостей в стиле doc. Рассмотрим этот сценарий:

  1. (Начальное состояние) Я использую планшет в ландшафтном режиме (две панели), активность A отображает список статей слева и некоторую статью справа.
  2. Я вращаю устройство, теперь активность A находится в режиме с одной панелью и отображает список статей.
  3. Я нажимаю на элемент списка, активность B начинается с открытия aritcle.
  4. Теперь я поворачиваю устройство обратно в альбомный режим.

Что происходит? Активность B отображает статью в натуральную величину, и, конечно, я хочу вернуться к двум панелям. Я не уверен, как это можно решить. Конечно, активность B может проверяться на многопанельный режим и заканчиваться, а активность A может проверять, что отображалась в последней статье … Это выглядит некрасиво. Мысли?

PS У меня есть подозрение, что приложение GMail использует однозадачный подход. Я не вижу каких-либо изменений активности при выборе электронной почты из списка. Он также ведет себя правильно в описанном мной сценарии.

В этой статье http://developer.android.com/guide/practices/tablets-and-handsets.html#Fragments Google говорит:

«Подход, который вы выбираете, зависит от вашего дизайна и личных предпочтений».

а также

«В то же время динамическая замена фрагментов для дизайна вашего телефона может сделать ваш код более сложным, потому что вы должны управлять всеми комбинациями фрагментов в коде действия (а не использовать альтернативные ресурсы макета для определения комбинаций фрагментов) и управлять задним стеком (Вместо того, чтобы нормальный стек активности обрабатывать обратную навигацию).