Работа с fragment android studio

Fragment (Фрагменты)

Фрагменты немного пугают новичков. Постараюсь объяснить как можно проще, чтобы отдельные фрагменты пазла сложились в единую картину.

Зачем?

Создатели операционной системы Android оказались недальновидными разработчиками. Не посоветовавшись с котами, они разработали систему под маленькие экраны телефонов. Но котам было неудобно пользоваться такими экранами, и тогда придумали планшеты.

Старые программы прекрасно на них запускались, но обнаружилось несколько недостатков. На больших экранах интерфейс выглядел не слишком элегантно, появились большие пустые пространства. И тогда возникла идея объединить два отдельных экрана из смартфона в один экран на планшете. Это самый классический пример применения фрагмента. По сути, это костыль. Возможно, если бы сразу подумали головой, то придумали бы более элегантное решение. Но теперь поздно пить «Боржоми», будем использовать предложенную концепцию.

Фрагменты были представлены в API 11 (Android 3.0), но в целях совместимости была написана специальная библиотека Android Support library для старых устройств. Долгое время существовало два класса Fragment: для новых устройств и для старых устройств. Названия методов и классов были очень похожи, и разработчики часто путались, смешивая в одном проекте два разных несовместимых класса. Спустя некоторое время решили отказаться от странного разделения, класс для новых устройств признали устаревшим, а класс из библиотеки поддержки старых устройств сменил своё полное имя и вошёл в состав AndroidX.

При желании можно было продолжить писать приложения в старом стиле, отслеживая размеры экрана. Но такой код получится слишком сложным. Пришлось бы писать один код для переключения от одной активности к другой при использовании смартфона и другой код, когда взаимодействие между объектами происходит на одном экране в планшете. Чтобы устранить это противоречие, были придуманы фрагменты. Хотя там тоже придётся писать много кода.

Несколько слов о том, как проще воспринимать фрагмент. Считайте, что фрагмент — это тот же компонент как Button, TextView или LinearLayout с дополнительными возможностями. Фрагмент, как и кнопку, нужно поместить на экран активности. Но фрагмент является модульным компонентом и один и тот же фрагмент можно встроить в две разные активности. С кнопкой такой номер не пройдёт. Для каждой активности вы должны создать свою отдельную кнопку, даже если их нельзя будет отличить друг от друга.

Фрагмент также немного похож на активность. Но фрагменты — это не замена активности, они не существуют сами по себе, а только в составе активностей. Поэтому в манифесте прописывать их не нужно. Но в отличие от стандартной кнопки, для каждого фрагмента вам придётся создавать отдельный класс, как для активности.

В составе активности есть специальный менеджер фрагментов, который может контролировать все классы фрагментов и управлять ими. О нём позже.

Фрагменты являются строительным материалом для приложения. Вы можете в нужное время добавить новый фрагмент, удалить ненужный фрагмент или заменить один фрагмент на другой. Точно так же мы собираем пазл — подносим фрагмент кота в общую картину, иногда ошибаемся и тогда заменяем кусочек пазла на другой и т.д.

Фрагмент может иметь свою разметку, а может обойтись без неё. Также у фрагмента есть свой жизненный цикл, во многом совпадающий с жизненным циклом активности. Пожалуй, это единственное сходство с активностью.

Имеются специальные виды фрагментов, заточенные под определённые задачи — ListFragment, DialogFragment и другие, которые изучим в других уроках.

Есть два варианта использования фрагментов в приложении (при желании можно использовать сразу оба варианта). Первый вариант заключается в том, что вы в разметке сразу указываете фрагмент с помощью тега fragment, так же как и с другими компонентами.

Второй вариант использует динамическое подключение фрагмента. Принцип следующий — в разметку помещается макет из группы ViewGroup, который становится контейнером для фрагмента. Обычно, для этой цели используют FrameLayout, но это не обязательное условие. И в нужный момент фрагмент замещает контейнер и становится частью разметки.

Поначалу фрагменты кажутся неудобными, так как количество кода увеличивается. Но если с ними работать постоянно, то станет понятнее их принцип.

Реакция разработчиков на появление фрагментов противоречива. Кто-то активно использует их в своих проектах, а кто-то их не переносит и использует альтернативные варианты. Похоже, в стане Гугла также идёт борьба между двумя группами программистов. Фрагменты постоянно развиваются, меняются и дорабатываются.

Первое знакомство

Для первого знакомства создадим стандартный проект на базе Empty Activity и вручную добавим фрагмент. Итак, после создания проекта выбираем из контекстного меню пакета New | Fragment | Fragment (Blank). В диалоговом окне мастера назначаем имя для фрагмента.

На этом этапе создание нового фрагмента напоминает создание новой активности. Мы создаём новый класс и автоматически генерируется макет для него fragment_cat.xml. Единственное отличие, в манифест ничего не добавляется.

Откроем макет фрагмента и немного отредактируем содержимое, добавив центрирование по центру. Также можно было добавить ImageView с изображением кота. Но не будем пока ничего усложнять.

В res/values/strings.xml содержится ресурс hello_blank_fragment. Изменим текст на что-то понятное:

Читайте также:  Ace stream android вылетает

Приготовления закончены. Осталось добавить фрагмент в активность. Открываем activity_main.xml и добавляем новый элемент.

В элементе fragment в атрибуте android:name указываем полное имя класса фрагмента.

Можно запустить проект и увидеть фрагмент внутри активности.

Жизненный цикл фрагмента

У фрагмента есть жизненный цикл, как у активности. Но число методов цикла гораздо больше. Откроем теперь файла класса фрагмента CatFragment и добавим новый код (выделено жирным).

Чтобы увидеть связь между жизненными циклами фрагмента и активности, добавим логи и в активность.

Снова запускаем проект и смотрим логи.

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

Два отдельных фрагмента

Мы научились размещать один фрагмент на экране активности. Ничто не мешает разместить на экране несколько фрагментов, которые являются контейнерами для компонентов. Давайте совместим на одном экране два старых примера — «Hello Kitty» и «Счётчик ворон/котов».

Повторим шаги создания нового фрагмента через готовый шаблон Fragment (Blank) и создадим два новых фрагмента KittyFragment и CounterFragment.

Разметку для KittyFragment копируем из старого примера.

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

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

Разметка для фрагмента counter_fragment.xml.

Код для класса CounterFragment. Здесь также мы добавляем весь код в onViewCreated().

Осталось разместить два фрагмента в activity_main.xml.

Запускаем проект и видим два приложения в одном. В верхней части мы здороваемся с котёнком, а в нижней считаем котов. Обратите внимание, что весь код сосредоточился в классах фрагментов, а в MainActivity нам вообще ничего не пришлось писать. Фрагменты работают независимо и мы можем писать код в разных модулях.

Источник

Фрагменты

Введение во фрагменты

Организация приложения на основе нескольких activity не всегда может быть оптимальной. Мир ОС Android довольно сильно фрагментирован и состоит из многих устройств. И если для мобильных аппаратов с небольшими экранами взаимодействие между разными activity выглядит довольно неплохо, то на больших экранах — планшетах, телевизорах окна activity смотрелись бы не очень в силу большого размера экрана. Собственно поэтому и появилась концепция фрагментов.

Фрагмент представляет кусочек визуального интерфейса приложения, который может использоваться повторно и многократно. У фрагмента может быть собственный файл layout, у фрагментов есть свой собственный жизненный цикл. Фрагмент существует в контексте activity и имеет свой жизненный цикл, вне activity обособлено он существовать не может. Каждая activity может иметь несколько фрагментов.

Для начала работы с фрагментами создадим новый проект с пустой MainActivity. И вначале создадим первый фрагмент. Но сразу стоит отметить, что не вся функциональность фрагментов по умолчанию может быть доступна в проекте, поскольку располагается в отдельной библиотеке — AndroidX Fragment library . И вначале необходимо подключить к проекту эту библиотеку в файле build.gradle .

Найдем в нем секцию dependencies , которая выглядит по умолчанию примерно так:

В ее начало добавим строку

То есть в моем случае получится

И затем нажмем на появившуюся ссылку Sync Now .

Фактически фрагмент — это обычный класс Java, который наследуется от класса Fragment . Однако как и класс Activity, фрагмент может использовать xml-файлы layout для определения графического интерфейса. И таким образом, мы можем добавить по отдельности класс Java, который представляет фрагмент, и файл xml для хранения в нем разметки интерфейса, который будет использовать фрагмент.

Итак, добавим в папку res/layout новый файл fragment_content.xml и определим в нем следующий код:

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

Теперь создадим сам класс фрагмента. Для этого добавим в одну папку с MainActivity новый класс. Для этого нажмем на папку правой кнопкой мыши и выберем в меню New -> Java Class . Назовем новый класс ContentFragment и определим у него следующее содержание:

Класс фрагмента должен наследоваться от класса Fragment .

Чтобы указать, что фрагмент будет использовать определенный xml-файл layout, идентификатор ресурса layout передается в вызов конструктора родительского класса (то есть класса Fragment).

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

Добавление фрагмента в Activity

Для использования фрагмента добавим его в MainActivity . Для этого изменим файл activity_main.xml , которая определяет интерфейс для MainActivity:

Для добавления фрамента применяется элемент FragmentContainerView . По сути FragmentContainerView представляет объект View, который расширяет класс FrameLayout и предназначен специально для работы с фрагментами. Собственно кроме фрагментов он больше ничего содержать не может.

Его атрибут android:name указывает на имя класса фрагмента, который будет использоваться. В моем случае полное имя класса фрагмента с учетов пакета com.example.fragmentapp.ContentFragment .

Код класса MainActivity остается тем же, что и при создании проекта:

Если мы запустим приложение, то мы увидим фактически тот же самый интерфейс, который мы могли бы сделать и через activity, только в данном случае интерфейс будет определен во фрагменте:

Стоит отметить, что Android Studio представляет готовый шаблон для добавления фрагмента. Собственно воспользуемся этим способом.

Для этого нажмем на папку, где находится класс MainActivity , правой кнопкой мыши и в появившемся меню выберем New -> Fragment -> Fragment(Blank) :

Данный шаблон предложить указать класс фрагмента и название файла связанного с ним класса разметки интерфейса.

Добавление логики к фрагменту

Фрагмент определяет кнопку. Теперь добавим к этой кнопки некоторое действие. Для этого изменим класс ContentFragment:

Здесь переопределен метод onViewCreated класса Fragment, который вызывается после создания объекта View для визуального интерфейса, который представляет данный фрагмент. Созданный объект View передается в качестве первого параметра. И далее мы можем получить конкретные элементы управления в рамках этого объекта View, в частности, TextView и Button, и выполнить с ними некоторые действия. В данном случае в обработчике нажатия кнопки в текстовом поле выводится текущая дата.

Читайте также:  Установить ролики для андроид

Добавление фрагмента в коде

Кроме определения фрагмента в xaml-файле интерфейса мы можем добавить его динамически в activity.

Для этого изменим файл activity_main.xml :

И также изменим класс MainActivity :

Метод getSupportFragmentManager() возвращает объект FragmentManager , который управляет фрагментами.

Объект FragmentManager с помощью метода beginTransaction() создает объект FragmentTransaction .

FragmentTransaction выполняет два метода: add() и commit(). Метод add() добавляет фрагмент: add(R.id.fragment_container_view, new ContentFragment()) — первым аргументом передается ресурс разметки, в который надо добавить фрагмент (это определенный в activity_main.xml элемент androidx.fragment.app.FragmentContainerView ). И метод commit() подтвержает и завершает операцию добавления.

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

Источник

Дизайн пользовательского интерфейса Android: работа с фрагментами

Новый API-интерфейс Fragment для Android, представленный в Android 3.0, позволяет упростить создание динамичного интерфейса. В этом учебном пособии вы узнаете, как преобразовать двухэкранный ListView и WebView в одноэранный вид, предназначенный для больших экранов, например, для планшетов.

Некоторые аспекты приложений или методов, используемых в этом руководстве, изменились с тех пор, как они были опубликованы. Это может затруднить выполнение нашей задачи. Мы рекомендуем посмотреть эти более новые уроки:

Шаги этого учебника будут более краткие, чем некоторые из наших предыдущих учебников; вам, возможно, придется просмотреть некоторые другие обучающие материалы для Android на этом сайте или даже в справочнике Android SDK, если вы не знакомы с какими-либо базовыми концепциями и классами Android, обсуждаемыми в этом руководстве. Окончательный образец кода, который идет вместе с этим уроком, доступен для загрузки в качестве открытого кода на Google.

Представляем фрагменты

Прежде чем мы начнем, давайте определим, что такое фрагмент. Фрагмент — это, как правило, часть пользовательского интерфейса с его собственным жизненным циклом. Если это звучит очень похоже на Activity, это потому, что оно похоже на него. Однако фрагмент отличается от Activity, поскольку он существует внутри него. Фрагмент не должен быть сопряжен с одним и тем же Activity каждый раз, когда он создается, что дает ему некоторую гибкость. Также как Activity, фрагмент не содержит элементов пользовательского интерфейса.

Шаг 0: Начало работы

В этом учебном пособии предполагается, что вы начнете работу с нашего урока по ListView. Вы можете загрузить код и начать работать с ним, хотя некоторые задания могут быть вам непонятны или вы можете загрузить код этого урока и следовать всем инструкциям в нём.

Шаг 1: Редизайн экранов

На следующем рисунке показано наше приложение Mobiletuts+ для чтения статей (урок ListView) до того, как был рассмотрен и применен дизайн фрагмента:

Эта разметка отлично работает на относительно небольшом экране телефона. Однако на большом экране, например, на 10-дюймовом экране Motorola Xoom на экране ListView очень много свободного места. Экран WebView выглядит хорошо, но немного пусто.

Здесь и появляются фрагменты: на больших экранах мы могли бы предоставить более эффективный пользовательский интерфейс, если бы мы могли отображать ListView на том же экране, что и WebView. Когда пользователь нажимает на определенный элемент ListView на панели слева, WebView с правой стороны обновляется, чтобы отобразить соответствующий контент. Этот тип разметки часто используется в программах для чтения электронной почты или документов. На следующем рисунке показан редизайн:

Шаг 2: Преобразование в дизайн на основе фрагментов

Теперь, мы знаем, как будет работать новая разметка экрана, мы также знаем, что два текущих действия необходимо будет преобразовать в фрагменты. Мы выполним преобразование в несколько этапов. Первый шаг заключается в том, чтобы оставить экраны визуально без изменений, но модифицировать каждый экран для использования фрагмента. Один фрагмент будет содержать текущий ListView, а другой будет содержать WebView. Затем мы перейдем к единственной реализации на экране, которая включает в себя обмен данными между элементами ListView и WebView, превращенными в фрагменты.

Во-первых, измените Project Build Target вашего приложения на Android 3.0. Чтобы сделать это в Eclipse, щелкните правой кнопкой мыши проект и выберите «Свойства». Перейдите в раздел Android и установите флажок рядом с Android 3.0. Мы не используем какие-либо API Google, поэтому достаточно версии Android Open Source Project. Затем нажмите кнопку «ОК».

Теперь у вас будет доступ к новым API, включая API фрагментов.

Примечание: В следующем уроке мы поговорим об использовании нового уровня совместимости, чтобы технологии, такие как API-интерфейс Fragment, работали в более ранних версиях Android. Пока же им потребуется устройство с Android 3.0, Honeycomb.

Шаг 3: Создание классов фрагментов

Создайте два новых класса Java для представления двух фрагментов: экранов ListView и WebView. Назовите их TutListFragment и TutViewerFragment. TutListFragment расширит класс ListFragment, а TutViewerFragment просто расширит класс Fragment.

В классе TutListFragment нам необходимо переопределить два метода: onListItemClick() и onCreate(). Содержание этих методов должно выглядеть вам знакомым; они похожи на те, что мы видели ранее в классе TutListActivity. Мы их скоро изменим, но пока не все. Вот список класса TutListFragment:

Класс TutViewerFragment немного проще. Мы используем тот факт, что фрагмент работает под тем же activity, которым он пользовался, и получает данные непосредственно из класса Fragment. Добавьте метод переопределения для метода onCreateView(). Теперь эти методы должны выглядеть так:

Читайте также:  Приключения поручика ржевского android защита

Возможность непосредственного доступа к экземпляру активности полезна, но позже создаст проблему. Что делать, если этот фрагмент находится на экране с фрагментом списка? В этом случае не произойдёт получения URL-адреса. Аналогично, в TutListFragment мы запускаем новое действие непосредственно, когда пользователь щелкает элемент в списке. Что делать, если TutViewFragment существовал в рамках одного activity? Если это так, запуск нового не имеет смысла. Мы вернемся и решим эти проблемы чуть позже в этом уроке.

Шаг 4: Добавление ресурсов макета фрагмента

Теперь создайте новый файл макета, называемый tutlist_fragment.xml, для фрагмента, содержащего список статей. Ресурс макета фрагмента использует тег и ссылается на созданный вами класс фрагментов.

Затем создайте аналогичный файл макета с именем tutview_fragment.xml:

Шаг 5: Обновление классов Activity

Теперь должны обновляться классы TutListActivity и TutViewerActivity. Класс TutListActivity имеет единственный метод onCreate(), который теперь должен быть обновлен для загрузки соответствующего ресурса макета фрагмента, созданного на предыдущем шаге, например:

Кроме того, следует отметить, что TutListActivity должен наследовать класс Activity, а не ListActivity.

Класс TutViewerActivity требует аналогичного изменения. Его метод onCreate() теперь должен выглядеть следующим образом:

Шаг 6: Проверка вашего прогресса

Попробуйте запустить приложение сейчас. Вы заметите, что оно делает именно то, что и раньше делало. Не очень интересно, не так ли? Однако весь пользовательский интерфейс теперь выполняется с использованием фрагментов. Это позволит сделать следующие изменения, которые нужно сделать, чтобы плавно перестроить всё, поскольку мы добавляем новый макет, который объединит два фрагмента на больших дисплеях. Однако, как вы могли заметить, связь между фрагментами обрабатывается идентично тому, как мы взаимодействуем между activity. Фактически, мы использовали знание о том, что активность каждого фрагмента в паре оставалась неизменной. Этого не будет, если у нас есть одно действие, которое содержит и управляет обоими фрагментами. Давайте исправим это в первую очередь.

Шаг 7: Изменение связи для TutListFragment

Как вы поняли на шаге 3, запуск активности непосредственно из объекта TutListFragment больше не имеет смысла. Пользовательский интерфейс WebView может, по сути, быть частью того же самого действия, что и List — это наше решение для больших экранов. В этом случае мы просто хотим обновить URL-адрес WebView во втором фрагменте.

Чтобы сделать это изменение, нам нужно сделать несколько вещей. Во-первых, сделаем фрагменты независимыми от активности, в которой они находятся. Для этого добавьте интерфейс обработчика в класс TutListFragment:

А затем активируйте его, обновив метод onListItemClickListener() следующим образом:

Затем, класс TutListActivity реализует интерфейс OnTutSelectedListener, например:

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

Шаг 8: Изменение связи для TutViewerFragment

Теперь перейдем к классу TutViewerFragment, который также необходимо обновить. Вместо того, чтобы узнать, какой URL для загрузки, фрагмент будет ожидать, нужно узнать, какой URL-адрес загружается. Таким образом, мы можем обновлять WebView напрямую и не воссоздавать фрагмент с каждой загрузкой.

Во-первых, измените класс TutViewerFragment на новый метод под названием updateUrl():

Затем удалите все функции из метода onCreateView(), за исключением вызова inflate(). Над классом TutViewerActivity, добавьте функциональные возможности для извлечения Intent и затем вызовите метод updateUrl(), например:

На этом этапе поведение приложения остается неизменным. Однако фрагменты могут существовать в пределах одного и того же действия или отдельных без дополнительных изменений кода.

Шаг 9: Добавление макета с двумя фрагментами

Теперь давайте создадим макет с обоими фрагментами, для использования в определенных ситуациях. В папке layout-land (которую вам может понадобиться создать) добавьте копию файла tutlist_fragment.xml. Это обеспечит разную ориентацию на любом экране. Портретный режим останется неизменным. Отредактируйте файл, чтобы выглядеть следующим образом с обоими фрагментами:

Это будет разделять экран по горизонтали между обоими фрагментами.

Шаг 10: Добавление динамического выбора

Теперь мы можем добавить в приложение некоторую простую логику для выбора между запуском нового действия (двух рабочий процесс экрана) и обновлением существующего фрагмента (рабочий процесс одного экрана).

Для этого обновите метод onTutSelected() в классе TutListActivity следующим образом:

Все это делает захват фрагмента и проверяет, является ли он частью существующего макета для Activity. Если нет, запускается активность просмотра, в противном случае вместо этого обновляется существующий фрагмент.

Шаг 11: Запуск приложения с добавлением новых фрагментов

На данный момент приложение будет работать в двух разных режимах: портрет не изменяется, а в ландшафте отображается ListView слева от WebView. На данный момент можно сделать несколько улучшений, но они относятся к настройке, оптимизации и других опций, в основном для красоты. Например, если вы находитесь в портретном режиме WebView и поворачиваете экран, в результате будет виден только экран WebView. Вы должны нажать назад, чтобы перейти к двойному виду. Оформление выходит за рамки данного руководства, но вы можете увидеть, как с помощью использования макетов и небольшого количества логики activity вы можете добиться мощных, но адаптивных экранов для различных устройств.

Заключение

API-интерфейс фрагмента помогает организовать компоненты интерфейса, так чтобы их можно было повторно использовать в разных activity. Таким образом, приложение может динамически корректировать свой макет и пользовательский интерфейсы с относительно небольшими усилиями в плане кодирования. Вы также видели, что приложение, которое создано с помощью фрагментов, легче реорганизовать. Еще лучше, чтобы любое приложение смогло использовать фрагменты через библиотеку совместимости, предоставляемую Google, которая совместима еще в Android 1.6.
Фрагментируйте пользовательский интерфейс приложений и создавайте удивительные пользовательские интерфейсы для каждого размера и формы экрана!

Источник

Оцените статью