FrameLayout – один из базовых контейнеров в Android, который позволяет размещать элементы интерфейса на экране приложения. Это самый простой контейнер среди всех имеющихся. С ним дворцов не построишь, но он существует в библиотеке не просто так.
FrameLayout особенно полезен, когда нужно расположить несколько компонентов поверх друг друга, например, для создания слоёв. Но он годится не только на это. Вперёд, к знакомству с FrameLayout.
Для чего применяется FrameLayout
Может показаться: если FrameLayout весь из себя такой негибкий и нефункциональный, то зачем он вообще? Почему бы не использовать контейнеры поинтереснее, например ConstraintLayout или LinearLayout?
И на это есть свои причины. Всё зависит от ваших целей. FrameLayout может показаться негибким и нефункциональным, если рассматривать его изолированно. Однако он имеет свои конкретные сценарии использования, когда он становится хорош в разработке интерфейса:
- Создание слоёв – FrameLayout идеально подходит для создания слоёв в интерфейсе, где нужно располагать элементы поверх друг друга.
- Overlay-элементы – FrameLayout часто используется для размещения небольших навигационных элементов, таких как кнопки, на верхней или нижней части экрана. Так они не мешают основному содержимому.
- Работа с видео и аудио – FrameLayout может быть полезен для создания видеоплееров или аудиоплееров, где контрольные элементы (пауза, воспроизведение, громкость и др.) могут находиться поверх видео или аудио.
- Простой контейнер для разработки – в некоторых случаях FrameLayout удобен для тестирования и разработки, так как он прост и не вносит дополнительных сложностей в разметку.
Наслоение компонентов
Создадим FrameLayout в корне файла XML-разметки.
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> |
Он растянут на всю ширину экрана, и пока не имеет внутри себя компонентов. Один из важных моментов при работе с FrameLayout – в какой последовательности размещаются элементы. Элемент, добавленный последним в разметке xml, будет находиться всегда сверху всех предыдущих. Управлять карнавалом можно также с помощью атрибута android:layout_margin – отступы, а также android:layout_gravity – в каком боку (или в центре) компонент будет располагаться.
Попробуем сделать что-нибудь красивое. Пускай это будет текст на фоне трёх разных картинок. То есть все четыре элемента наслоены друг на друга, а текст будет сверху – вишенка на торте.
Скачаем из интернета какой-нибудь симпатичный фон. Затем положим это изображение по пути Название проекта -> app -> src -> main -> res -> drawable. Чтобы отобразить картинку на экране, создадим внутри FrameLayout компонент ImageView:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageViewBlueBackground" android:layout_width="300dp" android:layout_height="190dp" app:srcCompat="@drawable/beautiful_blue_background"/> </FrameLayout> |
Вот как это выглядит в редакторе. Картинка в FrameLayout улеглась в левый верхний край экрана. Благодаря заданным размерам (ширина 300dp и высота 190dp), она занимает не всё место. Поэтому наглядно видно, куда её определил FrameLayout по умолчанию.
Попробуем добавить ей соседей.
Нужна картинка, которая будет местами прозрачная. Её тоже нужно будет скачать и забросить в папку drawable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageViewBlueBackground" android:layout_width="300dp" android:layout_height="190dp" app:srcCompat="@drawable/beautiful_blue_background"/> <ImageView android:id="@+id/imageViewStars" android:layout_width="230dp" android:layout_height="310dp" app:srcCompat="@drawable/stars"/> </FrameLayout> |
Эта добавленная картинка имеет цвет в тех местах, которые сейчас видны фиолетовым и синим. Остальное пространство у неё прозрачное. Именно поэтому за ней видно первую картинку. Такова задумка.
Как и ожидалось, этот компонент ImageView лёг точно так же, как и первый – в левый верхний край. Именно так FrameLayout поступает с компонентами по умолчанию.
Процедуру с добавлением картинки повторим ещё раз. На этот раз изображение также нужно с проблесками прозрачности.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageViewBlueBackground" android:layout_width="300dp" android:layout_height="190dp" app:srcCompat="@drawable/beautiful_blue_background"/> <ImageView android:id="@+id/imageViewStars" android:layout_width="230dp" android:layout_height="310dp" app:srcCompat="@drawable/stars"/> <ImageView android:id="@+id/imageViewPaint" android:layout_width="match_parent" android:layout_height="330dp" app:srcCompat="@drawable/paint"/> </FrameLayout> |
Как занимательно легла третья картинка – как будто бы звёзды идут из конца этого прерывистого эллипса. Впрочем, это счастливое совпадение – так вышло случайно.
Всё, три картинки имеются. Все начинаются слева сверху. Пора добавлять к ним текст – компонент TextView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageViewBlueBackground" android:layout_width="300dp" android:layout_height="190dp" app:srcCompat="@drawable/beautiful_blue_background"/> <ImageView android:id="@+id/imageViewStars" android:layout_width="230dp" android:layout_height="310dp" app:srcCompat="@drawable/stars"/> <ImageView android:id="@+id/imageViewPaint" android:layout_width="match_parent" android:layout_height="330dp" app:srcCompat="@drawable/paint"/> <TextView android:id="@+id/textView" android:text="Космос" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="60sp" android:textColor="@color/white" android:fontFamily="serif" android:shadowColor="@color/black" android:shadowRadius="15" android:layout_gravity="center_horizontal" android:layout_marginTop="60dp"/> </FrameLayout> |
Поигравшись с настройками TextView, мы получили прикольный результат. Как раз здесь и пригодились настройки android:layout_marginTop и android:layout_gravity. Первый атрибут дал возможность отлепить текст от самого верха и сдвинуть его чуть пониже. Второй атрибут подвинул текст в центр. Так что TextView располагается уже не как остальные компоненты по умолчанию в FrameLayout.
Вот так и происходит наслаивание компонентов друг на друга. Более того, можно это делать не так хаотично – а ровненько, даже соблюдая у них одинаковые размеры.
Полярная разметка
Кроме наслаивания, FrameLayout может быть хорош для создания полярной разметки. Полярной – потому что компоненты как бы находятся на полюсах: сверху (север), справа (восток), снизу (юг), слева (запад), а также по центру. Такая расстановка обычно удобна для содержимого и вспомогательных кнопок. Содержимое – по центру, а кнопки, скажем, снизу.
Реализуем подобную идею. Пускай это будет макет приложения-галереи. По центру будет ImageView с содержимым. По бокам будут кнопки для того, чтобы листать. Сверху слева будет кнопка возвращения назад. Снизу будут кнопки для удаления, редактирования и отправки изображения.
Конечно, функционал для компонентов мы им писать не будем – это уже совсем другая история. Но вот макетик интерфейса сделаем.
Для того, чтобы всё это выглядело интересно, рекомендую вместо текста на кнопках использовать изображения. Вместо текста “назад” на кнопке возвращения можно разместить стрелочку. Соответствующие картинки можно найти в интернетах и затем положить в папку drawable. Я решила нарисовать иконки в Adobe Illustrator, чтобы они были в одном стиле.
Итак, код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageViewStarryNight" android:layout_width="360dp" android:layout_height="360dp" app:srcCompat="@drawable/starry_night" android:layout_gravity="center"/> <Button android:id="@+id/buttonBack" android:layout_width="60dp" android:layout_height="60dp" android:background="@drawable/back" android:layout_gravity="start|top"/> <Button android:id="@+id/buttonLeft" android:layout_width="35dp" android:layout_height="60dp" android:background="@drawable/arrow_left" android:layout_gravity="start|center"/> <Button android:id="@+id/buttonRight" android:layout_width="35dp" android:layout_height="60dp" android:background="@drawable/arrow_right" android:layout_gravity="end|center"/> <Button android:id="@+id/buttonEdit" android:layout_width="55dp" android:layout_height="70dp" android:background="@drawable/edit" android:layout_gravity="start|bottom" android:layout_margin="15dp"/> <Button android:id="@+id/buttonShare" android:layout_width="55dp" android:layout_height="70dp" android:background="@drawable/share" android:layout_gravity="center|bottom" android:layout_margin="15dp"/> <Button android:id="@+id/buttonDelete" android:layout_width="55dp" android:layout_height="70dp" android:background="@drawable/delete" android:layout_gravity="end|bottom" android:layout_margin="15dp"/> </FrameLayout> |
Красота! Давайте разбираться, что к чему. Подсвеченные в коде строки содержат в себе атрибуты android:layout_gravity и android:layout_margin. Они позволяют управлять расположением компонента. Посмотрите, даже в простейшем и, казалось бы, негибком FrameLayout удалось создать нечто, похожее на интерфейс приложения. Всё потому, что автор учил матчасть (и вставил красивые иконки).
Для параметра android:layout_gravity так называемая “гравитация” задаётся в двух направлениях: по вертикали и горизонтали. android:layout_gravity=”center” – такая строка позволит задать расположение элемента в центре FrameLayout по обоим направлениям. Но что, если хочется, например, по горизонтали сделать в центре, а по вертикали прижать слева? Или наоборот? Или в правый нижний угол?
Здесь помогает символ вертикальной палки |. В итоге, для правого нижнего угла получим android:layout_gravity=”end|bottom”. Эта запись означает “расположить справа (в конце) и снизу”. Именно такую настройку “гравитации” имеет кнопка удаления. Как видно, она как раз располагается на макете в правом нижнем углу.
Однако, важно понимать, что для создания сложных макетов и интерфейсов, особенно с большим количеством элементов, FrameLayout не годится. Придётся прибегнуть к более интересным контейнерам, таким как ConstraintLayout или LinearLayout. Они будут более подходящими вариантами, так как предоставляют более гибкую систему расположения элементов.
Итак, FrameLayout – это инструмент, который следует использовать в тех сценариях, где его ограниченная функциональность соответствует требованиям проекта.