2. Добавление фрагментов в Activity. Менеджер фрагментов
Рассмотрим процесс создания фрагментов и добавления их в Activity.
Как правило, фрагмент добавляет часть пользовательского интерфейса в Activity, и этот интерфейс встраивается в общую иерархию представлений Activity. Разработчик может добавить фрагмент в макет Activity двумя способами:
объявив фрагмент в файле макета Activity;
программно, добавив фрагмент в существующий объект ViewGroup.
Рассмотрим оба этих способа и попутно разберемся, как же создавать и использовать фрагменты.
Объявление фрагмента в макете Activity
Создадим тестовое приложение с одним Activity.
Создадим два пустых класса - MenuFragment и DetailsFragment. Оба класса наследуются от базового класса android.support.v4.app.Fragment.
Перейдем в макет Activity, найдем компонент под названием <fragment> и добавим их в макет, указав для каждого фрагмента соответствующий класс фрагмента, который мы только что создали. В нашем тестовом примере макет будет выглядеть следующим образом
Теперь перейдем непосредственно к процессу создания фрагментов.
Создание фрагмента
Фрагмент обычно используется как часть пользовательского интерфейса операции, при этом он добавляет в операцию свой макет.
Чтобы создать макет для фрагмента, разработчик должен реализовать метод обратного вызова onCreateView(), который система Android вызывает, когда для фрагмента наступает время отобразить свой макет. Реализация этого метода должна возвращать объект View, который является корневым в макете фрагмента.
Чтобы возвратить макет из метода onCreateView(), можно выполнить его раздувание из ресурса макета, определенного в XML-файле. Для этой цели метод onCreateView() предоставляет объект LayoutInflater.
Создадим макеты для двух наших фрагментов, fragment_menu.xml и fragment_details.xml.
Теперь перейдем в классы фрагментов и переопределим метод обратного вызова onCreateView().
Чтобы показать преимущество фрагментов перед использованием Activity напрямую, создадим макет Activity для ландшафтной ориентации мобильного устройства.
Создадим макет activity_main, указав квалификатор Orientation как Landscape (такой ресурс называется альтернативным, мы будем говорить о таких ресурсах позже).
Этот макет будет добавлен в папку layout-land. Создадим макет с двумя фрагментами. Мы не меняем макеты и код класса фрагментов, а просто в альтернативном макете Activity изменяем компоновку фрагментов в окне.
Запустим приложение и повернем эмулятор, чтобы перевести устройство в ландшафтный режим.
Как мы видим, теперь фрагменты располагаются в горизонтальный ряд и наше приложение будет корректно отображаться в ландшафтном режиме.
Добавление макета через объявление его в макете Activity реализуется достаточно просто, но имеет один важный недостаток - мы не можем динамически менять фрагменты во время работы приложения. Чтобы добиться такого поведения от фрагментов, необходимо добавлять их программно, что мы и рассмотрим далее.
Программное добавление фрагментов
Вместе с программным добавлением фрагментов рассмотрим вопрос передачи данных из фрагмента в фрагмент и вопрос взаимодействия фрагмента с Activity, к которому он прикреплен.
Модифицируем фрагменты следующим образом - добавим в фрагмент MenuFragment поле ввода и кнопку. По нажатию на кнопку, данные из поля ввода будут переданы в DetailsFragment и выведены на экран.
Программирование MenuFragment
Модифицируем фрагмент MenuFragment. Добавим в макет фрагмента поле ввода и кнопку. По нажатию на кнопку мы должны вызывать метод Activity, в котором будет осуществлено динамическое добавление
Добавим переопределение для методов жизненного цикла. Метод onCreateView() вызывается в момент создания дерева элементов графического интерфейса. В теле метода мы должны осуществить inflate макета фрагмента, после чего передать дерево элементов как результат работы метода. Метод onViewCreated() вызывается уже после успешного создания графического интерфейса макета. В этом методе можно получить доступ и манипулировать элементами UI. Добавим обработчик нажатия на кнопку
MenuFragment.java
@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
returninflater.inflate(R.layout.fragment_menu, container,false);}@OverridepublicvoidonViewCreated(@NonNullView view, @NullableBundle savedInstanceState) { super.onViewCreated(view, savedInstanceState);Button button =view.findViewById(R.id.button);button.setOnClickListener(v -> {EditText et =view.findViewById(R.id.editText);String text =et.getText().toString();// Вызов метода Activity и отправка данных });}
Для взаимодействия с Activity, к которому прикреплен фрагмент, можно воспользоваться методом getActivity() фрагмента, после чего предусмотреть в Activity публичный метод для вызова из фрагмента.
Однако, корректный и безопасный способ состоит в создании интерфейса, который будет реализовывать Activity и получение ссылки на Activity во время вызова метода жизненного цикла onAttach() (этот метод вызывается в момент присоединения Activity) и обнулении ссылки на Activity во время вызова метода жизненного цикла onDetach() (метод вызывается в момент отсоединения фрагмента).
Отредактируем класс MainActivity. Добавим фрагмент MenuFragment в методе onCreate(). Для управления фрагментами в Activity используется объект FragmentManager. Чтобы его получить, следует вызвать метод getSupportFragmentManager().
Получим объект менеджера фрагментов и добавим фрагмент в макет Activity.
В методе onFragmentInteraction() необходимо создать объект DetailsFragment, передать строку с текстом и добавить его в Activity. Для того чтобы это сделать, необходимо запрограммировать класс DetailsFragment.
Программирование DetailsFragment
Модифицируем фрагмент DetailsFragment. Для класса фрагмента необходимо добавить конструктор без параметров (для того чтобы фрагмент могла восстановить ОС), создание фрагмента лучше всего реализовать с помощью статического фабричного метода. Передача данных в фрагмент осуществляется с помощью механизма Arguments.
В методе OnViewCreated() установим значение текстового поля - строку, которая была передана с помощью механизма Arguments.