При розробці додатків для підтримки широкого діапазону розмірів екрану, можете використовувати свої фрагменти в різних конфігураціях макета для оптимізації роботи користувачів, ґрунтуючись на доступному просторі екрана.
Наприклад, на пристрої у вигляді телефонної трубки може бути доцільним відобразити тільки один фрагмент одночасно для одношарового інтерфейсу користувача. І навпаки, ви можете встановити фрагменти пліч-о-пліч на планшетнику, який має більш широкий розмір екрану для відображення додаткової інформації для користувача.
Два фрагменти, які відображаються в різних конфігураціях для тієї ж самої activity на екранах різних розмірів. На великому екрані обидва фрагмента розміщені пліч-о-пліч, а на пристрої у вигляді трубки, одночасно показується тільки один фрагмент, тому фрагменти повинні заміняти один одного, коли користувач переходить.
Клас FragmentManager надає методи, які дозволяють додавати, видаляти і замінювати фрагменти activity під час виконання для того, щоб створити динамічне використання.
Додавання фрагменту до Activity під час виконання
Замість визначення фрагментів для activity в файлі макета - як показано в попередньому уроці, з елементом <fragment> ви можете додати фрагмент до activity під час виконання робіт. Це необхідно, якщо плануєте змінювати фрагменти протягом життя activity.
Для виконання таких транзакцій, як додати або видалити фрагмент, необхідно використовувати FragmentManager для створення FragmentTransaction, який забезпечує API для додавання, видалення, заміни і виконання інших операцій з фрагментами.
Якщо ваша activity дозволяє видалення і заміну фрагментів, то ви повинні додати початковий фрагмент(и) в activity з методом onCreate() activity.
Важливе правило при роботі з фрагментами - особливо при додаванні фрагментів під час виконання – полягає в тому, що ваш макет activity повинен включати в себе контейнер View, в який ви можете вставити фрагмент.
Нижче наведена компоновка є альтернативою компоновки, показаної в попередньому занятті, в якому показується одночасно тільки один фрагмент. Для того, щоб замінити один фрагмент на інший, макет activity включає в себе порожню FrameLayout, яка працює як контейнер фрагмента.
Зверніть увагу, що ім'я файлу збігається з файлом макета з попереднього уроку, але каталог макету не має позначки large, тому ця схема використовується, коли екран пристрою менший, ніж large, тому що екран не підходить одночасно для обох фрагментів.
res/layout/news_articles.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Усередині вашої activity, викликається getSupportFragmentManager() для отримання FragmentManager, використовуючи API Support Library. Потім викликається beginTransaction() для створення FragmentTransaction і викликається add(), щоб додати фрагмент.
Ви можете виконати транзакцію кількох фрагментів для activity, використовуючи ту ж саму FragmentTransaction. Коли будете готові, щоб зробити зміни, то повинні викликати commit().
Приклад, як додати фрагмент до попереднього макета:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Перевірка, що activity використовує версію макету з
// з контейнером фрагмента FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// Тим не менш, якщо ми відновлюємося з попереднього стану
// то нам не треба нічого робити, а повинні повернути або
// ми можемо завершити фрагментами, які перекриваються.
if (savedInstanceState != null) {
return;
}
// Створюємо новий фрагмент, який буде поміщений в макет activity
HeadlinesFragment firstFragment = new HeadlinesFragment();
// У випадку, коли activity запущена з особливими інструкціями
// мети, додаткові наміри входять як аргументи для фрагмента
firstFragment.setArguments(getIntent().getExtras());
// Додаємо фрагмент до 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
Тому, що фрагмент був доданий в контейнер FrameLayout під час виконання, - замість визначення його в макеті activity за допомогою елемента <fragment> - activity може видалити фрагмент і замінити його на інший.
Заміна одного фрагмента на інший
Процедура заміни фрагмента схожа на додавання фрагмента, але вимагає метода replace() замість add().
Майте на увазі, що при виконанні таких транзакцій фрагмента, як заміна або видалення його, часто доцільно дозволити користувачеві переміщатися назад і "undo" ("скасувати") зміни. Щоб користувач міг переміщатися назад при транзакціях з фрагментами, ви повинні викликати addToBackStack(), перш ніж виконаєте FragmentTransaction.
Примітка: При видаленні або заміні фрагмента і додаванні транзакції в задній стек, фрагмент, який видаляється, буде зупинений (не руйнується). Якщо користувач переходить назад, щоб відновити фрагмент, то він перезавантажується. Якщо ви не додаєте транзакцію в задній стек, то фрагмент буде знищений при видаленні або заміні.
Приклад заміни одного фрагмента іншим:
// Створити фрагмент і дати йому аргумент, який вказує, яку статтю слід показати
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Замінити все у вигляді контейнера фрагмента з цього фрагмента,
// і додати транзакцію в задній стек, щоб користувач міг повернутися назад
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Виконати транзакцію
transaction.commit();
Метод addToBackStack() приймає необов'язковий строковий параметр, який визначає унікальне ім'я для транзакції. Ім'я не потрібно, якщо ви не плануєте виконувати складні операції, використовуючи API FragmentManager.BackStackEntry.
(Джерело: developer.android.com)