Как создать фрагмент в android studio

от admin

Fragments Tutorial With Example In Android Studio

What is a fragment in Android?
Fragments are reusable pieces of UI.

What is the purpose of using fragments?
The purpose of using fragments to build a flexible UI that we can dynamically add the UI or remove it during the runtime.

So, let’s start building the Android Fragment-APP example with the source code.
NOTE In this example, I use Android Studio 3.3

1.1: Fragments

A Fragment is a self-contained component with its own user interface (UI) and lifecycle that can be reused in different parts of an app's UI. This chapter explains how a Fragment can be useful for a UI design. (A Fragment can also be used without a UI, in order to retain values across configuration changes, but this chapter does not cover that usage.)

Understanding fragments

A Fragment is a class that contains a portion of an app's UI and behavior, which can be added as part of an Activity UI. While a single Fragment can be shared by different activities, each specific instance of the Fragment is exclusively tied to the Activity that hosts it.

A Fragment is like a miniature Activity . Although it must be hosted by an Activity , a Fragment has its own lifecycle. Also like an Activity , a Fragment receives its own input events. For example, the standard date picker is a Fragment —an instance of DialogFragment , a subclass of Fragment —that enables the user to input a date. The standard date picker shows a dialog window floating on top of the Activity window.

 The date picker (left), and a diagram of the activity and fragment for the date picker (right)

For maximum reusability, a single Fragment should contain the code to define its layout and its behavior for user interaction.

In the above figure, on the right side, the numbers mean the following:

  1. The Activity before the user event that adds the date picker.
  2. A user event, such as clicking a button, adds the date picker to the UI of the Activity .
  3. The date picker, an instance of DialogFragment (a subclass of Fragment ), which displays a dialog floating on top of the Activity .

 Tap Open to open the fragment, and Close to close the fragment.

A Fragment can be a static part of an Activity UI so that it remains on the screen during the entire lifecycle of the Activity , or it can be a dynamic part of the UI, added and removed while the Activity is running. For example, the Activity can include buttons to open and close the Fragment .

The benefits of using fragments

Like any Fragment , the date picker includes the code for user interaction (in this case, selecting the date). The Fragment also has its own lifecycle—it can be added and removed by the user. These two characteristics of Fragment let you:

  • Reuse aFragment . Write the Fragment code once, and reuse the Fragment in more than one Activity without having to repeat code.
  • Add or remove aFragmentdynamically. Add, replace, or remove a Fragment from an Activity as needed.
  • Integrate a mini-UI within theActivity . Integrate a Fragment with an Activity UI or overlay the UI, so that the user can interact with the Fragment UI without leaving the Activity .
  • Retain data instances after a configuration change. Since a Fragment has its own lifecycle, it can retain an instance of its data after a configuration change (such as changing the device orientation).
  • Represent sections of a layout for different screen sizes. Encapsulating an interactive UI within a Fragment makes it easier to display the interactive UI on different screen sizes.

For an example of how a Fragment can be used to show a UI in different screen sizes, start a new Android Studio project for an app and choose the Settings Activity template. Run the app.

 Device master screen (left) and detail screen (right)

The template provides a Fragment to show the list of categories (left side of figure below), and a Fragment for each category (such as General) to show the settings in that category (right side of figure below). In layout terms, the list screen is known as the "master," and the screen showing the settings in a category is known as the "detail."

If you run the same app on a large-screen tablet in landscape orientation, the UI for each Fragment appears with the master and detail panes side by side, as shown below.  Master/detail layout for tablets

Using a fragment

The general steps to use a Fragment :

  1. Create a subclass of Fragment .
  2. Create a layout for the Fragment .
  3. Add the Fragment to a host Activity , either statically or dynamically.

Creating a fragment

To create a Fragment in an app, extend the Fragment class, then override key lifecycle methods to insert your app logic, similar to the way you would with an Activity class.

Instead of extending the base Fragment class, you can extend one of these other, more specific Fragment subclasses:

    Displays a floating dialog, such as a date picker or time picker. : Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter ). : Displays a hierarchy of Preference objects as a list, similar to PreferenceActivity . This is useful when creating a "settings" Activity for your app.

You can create a Fragment in Android Studio by following these steps:

  1. In Project: Android view, expand app > java and select the folder containing the Java code for your app.
  2. Choose File > New > Fragment > Fragment (Blank).
  3. Name the Fragment something like SimpleFragment, or use the supplied name ( BlankFragment ).

If your Fragment has a UI, check the Create layout XML option if it is not already checked. Other options include:

  • Include fragment factory methods: Include sample factory method code to initialize the Fragment arguments in a way that encapsulates and abstracts them. Select this option if the number of arguments would make a constructor too complex.
  • Include interface callbacks: Select this option if you want to include sample code that defines an interface in the Fragment with callback methods that enable the Fragment to communicate with its host Activity .

Click Finish to create the Fragment .

If you named the Fragment SimpleFragment , the following code appears in the Fragment :

All subclasses of Fragment must include a public no-argument constructor as shown, with the code public SimpleFragment() . The Android framework often re-instantiates a Fragment class when needed, in particular during state restore. The framework needs to be able to find this constructor so it can instantiate the Fragment .

Creating a layout for a fragment

If you check the Create layout XML option when creating a Fragment , the layout file is created for you and named after the Fragment , for example "fragment_simple.xml" for SimpleFragment . As an alternative, you can manually add a layout file to your project. The layout includes all UI elements that appear in the Fragment .

For maximum reusability, make your Fragment self-contained. A single Fragment should contain all necessary code to define its layout and its behavior for user interaction. Similar to an Activity , a Fragment inflates its layout to make it appear on the screen. Android calls the onCreateView() callback method to display a Fragment . Override this method to inflate the layout for a Fragment , and return a View that is the root of the layout for the Fragment .

For example, if you chose Fragment (Blank) with just the Create layout XML option, and you name the Fragment SimpleFragment, the following code is generated in SimpleFragment :

The container parameter passed to onCreateView() is the parent ViewGroup from the Activity layout. Android inserts the Fragment layout into this ViewGroup .

The onCreateView() callback provides a LayoutInflater object to inflate the UI for the Fragment from the fragment_simple layout resource. The method returns a View that is the root of the layout for the Fragment .

The savedInstanceState parameter is a Bundle that provides data about the previous instance of the Fragment , in case the Fragment is resuming.

The inflate() method inside onCreateView() displays the layout:

The inflate() method takes three arguments:

  • The resource ID of the layout you want to inflate ( R.layout.fragment_simple ).
  • The ViewGroup to be the parent of the inflated layout ( container ).
  • A boolean indicating whether the inflated layout should be attached to the ViewGroup ( container ) during inflation. This should be false because the system is already inserting the inflated layout into the container. Passing true would create a redundant ViewGroup in the final layout.

Tip: The Fragment class contains other lifecycle callback methods to override besides onCreateView() , such as onCreate() , onStart() , onPause() , and onStop() . The only lifecycle callback you need to inflate the layout is onCreateView() . To learn about other lifecycle callbacks, see the lesson on Fragment lifecycle and communications.

Adding a fragment to an activity

A Fragment must be hosted by an Activity and included in its layout. There are two ways you can use a Fragment in an Activity layout:

Add the Fragment statically, inside the XML layout file for the Activity , so that it remains on the screen during the entire lifecycle of the Activity .

For example, you may want to devote a portion of a UI for an Activity to a Fragment that provides its own user interaction and behavior, such as a set of social media "Like" buttons. You can add this Fragment to the layouts of different activities.

Add the Fragment dynamically, using fragment transactions. During the lifecycle of the Activity , your code can add or remove the Fragment , or replace it with another Fragment , as needed.

Adding a fragment statically

Declare the Fragment inside the layout file for the Activity (such as activity_main.xml ) using the <fragment> tag. You can specify layout properties for the Fragment as if it were a View . For example, the following shows two Fragment objects included in the Activity layout:

When the system creates the Activity layout, it instantiates each Fragment specified in the layout, and calls the onCreateView() method for each one, to retrieve the layout for each Fragment . Each Fragment returns a View , and the system inserts this View directly in place of the <fragment> element.

The code above uses the android:id attribute to identify each Fragment element. The system uses this id to restore the Fragment if the Activity is restarted. You also use it in your code to refer to the Fragment .

Adding a fragment dynamically

A great feature of the Fragment class is the ability to add, remove, or replace a Fragment dynamically, while an Activity is running. A user performs an interaction in the Activity , such as tapping a button, and the Fragment appears in the UI of the Activity . The user taps another button to remove the Fragment .

To add a Fragment , your Activity code needs to specify a ViewGroup as a placeholder for the Fragment , such as a LinearLayout or a FrameLayout :

To manage a Fragment in your Activity , create an instance of the Fragment , and an instance of FragmentManager using getSupportFragmentManager() . With FragmentManager you can use FragmentTransaction methods to perform Fragment operations while the Activity runs.

Fragment operations are wrapped into a transaction so that all of the operations finish before the transaction is committed for the final result. You start a transaction with beginTransaction() and end it with commit() .

Within the transaction you can:

  • Add a Fragment using add() .
  • Remove a Fragment using remove() .
  • Replace a Fragment with another Fragment using replace() .
  • Hide and show a Fragment using hide() and show() .

The best practice for instantiating the Fragment in the A ctivity is to provide a newinstance() factory method in the Fragment . For example, if you choose New > Fragment > Fragment Blank to add a Fragment to your Android Studio project, and you select the Include fragment factory methods option, Android Studio automatically adds a newinstance() method to the Fragment as a factory method to set arguments for the Fragment when the Fragment is called by the Activity .

Add a simple newinstance() method to SimpleFragment , and instantiate the Fragment in MainActivity :

  1. Open SimpleFragment , and add the following method to the end for instantiating the Fragment :
  2. In the Activity , instantiate the Fragment by calling the newInstance() method in SimpleFragment :

Tip: Use the Support Library version— getSupportFragmentManager() rather than getFragmentManager() —so that the app remains compatible with devices running earlier versions of Android platform.

Use beginTransaction() with an instance of FragmentTransaction to start a series of edit operations on the Fragment :

You can then add a Fragment using the add() method, and commit the transaction with commit() . For example:

The first argument passed to add() is the ViewGroup in which the fragment should be placed (specified by its resource ID fragment_container ). The second parameter is the fragment to add.

In addition to the add() transaction, call addToBackStack(null) in order to add the transaction to a back stack of Fragment transactions. This back stack is managed by the Activity . It allows the user to return to the previous Fragment state by pressing the Back button:

To replace a Fragment with another Fragment , use the replace() method. To remove a Fragment , use remove() . Once you've made your changes with FragmentTransaction , you must call commit() for the changes to take effect.

The following shows a transaction that removes the Fragment simpleFragment using remove() :

In addition to learning about how a Fragment can be added, replaced, and removed, you should also learn how to manage the lifecycle of a Fragment within the Activity , as described in the lesson on Fragment lifecycle and communications.

Фрагменты

Кот из фрагментов

Существует два основных подхода в использовании фрагментов.

Первый способ основан на замещении родительского контейнера. Создаётся стандартная разметка и в том месте, где будут использоваться фрагменты, размещается контейнер, например, FrameLayout. В коде контейнер замещается фрагментом. При использовании подобного сценария в разметке не используется тег fragment, так как его нельзя менять динамически. Также вам придётся обновлять ActionBar, если он зависит от фрагмента. Здесь показан такой пример.

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

Fragment

Fragment

Основные классы

Сами фрагменты наследуются от androidx.fragment.app.Fragment. Существует подклассы фрагментов: ListFragment, DialogFragment, PreferenceFragment, WebViewFragment и др. Не исключено, что число классов будет увеличиваться, например, появился ещё один класс MapFragment.

Для взаимодействия между фрагментами используется класс android.app.FragmentManager — специальный менеджер по фрагментам.

Как в любом офисе, спецманагер не делает работу своими руками, а использует помощников. Например, для транзакций (добавление, удаление, замена) используется класс-помощник android.app.FragmentTransaction.

Для сравнения приведу названия классов из библиотеки совместимости:

  • android.support.v4.app.FragmentActivity
  • android.support.v4.app.Fragment
  • android.support.v4.app.FragmentManager
  • android.support.v4.app.FragmentTransaction

Как видите, разница в одном классе, который я привёл первым. Он используется вместо стандартного Activity, чтобы система поняла, что придётся работать с фрагментами. На данный момент студия создаёт проект на основе ActionBarActivity, который является подклассом FragmentActivity.

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

В 2018 году Гугл объявила фрагменты из пакета androd.app устаревшими. Заменяйте везде на версию из библиотеки совместимости. В 2020 году уже используют пакет androidx.fragment.app.

В версии Support Library 27.1.0 появились новые методы requireActivity() и requireContext(), которые пригодятся при написании кода, когда требуется наличие активности и нужно избежать ошибки на null.

Общий алгоритм работы с фрагментами будет следующим:

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

Также, как в активности, вы создаёте различные методы типа onCreate() и т.д. Если фрагмент имеет разметку, то используется метод onCreateView() — считайте его аналогом метода setContentView(), в котором вы подключали разметку активности. При этом метод onCreateView() возвращает объект View, который является корневым элементом разметки фрагмента.

Разметку для фрагмента можно создать программно или декларативно через XML.

Создание разметки для фрагмента ничем не отличается от создания разметки для активности. Вот отрывок кода из метода onCreateView():

Глядя на этот код, вы должные понять, что фрагмент использует разметку из файла res/layout/first_fragment.xml, которая содержит кнопку с идентификатором android:id=»@+id/button_first». Здесь также прослеживается сходство с подключением компонентов в активности. Обратите внимание, что перед методом findViewById() используется view, так как этот метод относится к компоненту, а не к активности, как мы обычно делали в программах, когда просто опускали имя активности. Т.е. в нашем случае мы ищем ссылку на кнопку не среди разметки активности, а внутри разметки самого фрагмента.

Нужно помнить, что в методе inflate() последний параметр должен иметь значение false в большинстве случаев.

FragmentManager

Класс FragmentManager имеет два метода, позволяющих найти фрагмент, который связан с активностью:

findFragmentById(int id) Находит фрагмент по идентификатору findFragmentByTag(String tag) Находит фрагмент по заданному тегу

Методы транзакции

Мы уже использовали некоторые методы класса FragmentTransaction. Познакомимся с ними поближе

add() Добавляет фрагмент к активности remove() Удаляет фрагмент из активности replace() Заменяет один фрагмент на другой hide() Прячет фрагмент (делает невидимым на экране) show() Выводит скрытый фрагмент на экран detach() (API 13) Отсоединяет фрагмент от графического интерфейса, но экземпляр класса сохраняется attach() (API 13) Присоединяет фрагмент, который был отсоединён методом detach()

Методы remove(), replace(), detach(), attach() не применимы к статичным фрагментам.

Перед началом транзакции нужно получить экземпляр FragmentTransaction через метод FragmentManager.beginTransaction(). Далее вызываются различные методы для управления фрагментами.

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

Аргументы фрагмента

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

  • Активность может создать фрагмент и установить аргументы для него
  • Активность может вызвать методы экземпляра фрагмента
  • Фрагмент может реализовать интерфейс, который будет использован в активности в виде слушателя

Фрагмент должен иметь только один пустой конструктор без аргументов. Но можно создать статический newInstance с аргументами через метод setArguments().

Доступ к аргументам можно получить в методе onCreate() фрагмента:

Динамически загружаем фрагмент в активность.

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

Вызываем метод в активности:

Если фрагмент должен сообщить о своих действиях активности, то следует реализовать интерфейс.

Управление стеком фрагментов

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

Чтобы добавить транзакцию в стек, вызовите метод FragmentTransaction.addToBackStack(String) перед завершением транзакции (commit). Строковый аргумент — опциональное имя для идентификации стека или null. Класс FragmentManager имеет метод popBackStack(), возвращающий предыдущее состояние стека по этому имени.

Если вы вызовете метод addToBackStack() при удалении или замещении фрагмента, то будут вызваны методы фрагмента onPause(), onStop(), onDestroyView().

Когда пользователь нажимает на кнопку возврата, то вызываются методы фрагмента onCreateView(), onActivityCreated(), onStart() и onResume().

Рассмотрим пример реагирования на кнопку Back в фрагменте без использования стека. Активность имеет метод onBackPressed(), который реагирует на нажатие кнопки. Мы можем в этом методе сослаться на нужный фрагмент и вызвать метод фрагмента.

Теперь в классе фрагмента прописываем метод с нужным кодом.

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

Интеграция Action Bar/Options Menu

Фрагменты могут добавлять свои элементы в панель действий или меню активности. Сначала вы должны вызвать метод Fragment.setHasOptionsMenu() в методе фрагмента onCreate(). Затем нужно задать настройки для методов фрагмента onCreateOptionsMenu() и onOptionsItemSelected(), а также при необходимости для методов onPrepareOptionsMenu(), onOptionsMenuClosed(), onDestroyOptionsMenu(). Работа методов фрагмента ничем не отличается от аналогичных методов для активности.

В активности, которая содержит фрагмент, данные методы автоматически сработают.

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

Код для активности:

Код для фрагмента:

Связь между фрагментом и активностью

Экземпляр фрагмента связан с активностью. Активность может вызывать методы фрагмента через ссылку на объект фрагмента. Доступ к фрагменту можно получить через методы findFragmentById() или findFragmentByTag().

Фрагменты

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

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

Фрагменты в Android

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

Подключение фрагментов и AndroidX Fragment library в Android и Java

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

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

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

Подключение фрагментов и AndroidX Fragment library в Android и Java и Gradle

И затем нажмем на появившуюся ссылку 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).

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

Фрагменты в Android Studio и Java

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

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

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

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

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

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

Создание фрагмента для Android и Java

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

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

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

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

Добавление фрагмента в Android Studio и Java

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

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

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

Добавление фрагмента в AndroidX Fragment Library и Java

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

Кроме определения фрагмента в 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 в разметке интерфейса.

Читать:
Bindingsource c как использовать

Related Posts