LinearLayout – это один из самых простых макетов (layouts) в Android, который позволяет размещать элементы внутри себя. Делает он это в весьма нехитрой форме – в виде линейной последовательности (поэтому Linear в названии). Друг за дружкой. Компоненты внутри LinearLayout могут размещаться друг за другом либо горизонтально, либо вертикально.
Этот макет подходит для создания простых интерфейсов. Кроме того, он имеет одну очень классную и жизненно необходимую фишку – веса компонентов. Обо всём этом поговорим в статье.
Создание LinearLayout
Для создания LinearLayout в файле XML макета интерфейса нужно прописать тег <LinearLayout></LinearLayout>. В открывающем теге прописываются свойства макета. В свою очередь, между открывающим и закрывающим тегами располагаются компоненты. А свойство android:orientation позволяет задать ориентацию (vertical или horizontal).
Вот пример пока что пустого, без компонентов, LinearLayout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="horizontal" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> </LinearLayout> |
Размещение компонентов
Внутренние компоненты у LinearLayout располагаются друг за другом в указанной ориентации (вертикальной или горизонтальной). Вы можете добавлять компоненты внутри LinearLayout так же, как вы бы добавляли их в другие макеты. LinearLayout – это уже немного более сложный макет, чем, например, FrameLayout.
Посмотрим, как будет выглядеть парочка компонентов в LinearLayout с ориентацией horizontal.
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 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="horizontal" android:gravity="fill_vertical" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:text="Надпись на заборе" android:layout_width="80dp" android:layout_height="wrap_content" android:gravity="center"/> <Switch android:id="@+id/switcher" android:text="Свет на кухне" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:id="@+id/button" android:text="reboot" android:layout_width="85dp" android:layout_height="wrap_content"/> <ImageView android:id="@+id/imageView" android:layout_width="60dp" android:layout_height="60dp" app:srcCompat="@drawable/dragon"/> </LinearLayout> |
Всё просто и понятно – по порядку по горизонтали. При этом каждый компонент начинается ровно по верхней кромке. Но это не обязательно.
Дело в том, что можно менять параметр android:gravity у LinearLayout. Посмотрите, как изменится картина, если задать другие значения (а не fill_vertical).
1 |
android:gravity="clip_vertical" |
1 |
android:gravity="center_horizontal" |
1 |
android:gravity="center_vertical" |
1 |
android:gravity="center" |
Почему всё горизонтально да горизонтально? Сделаем так, чтобы элементы находились друг за другом вертикально. Этого можно добиться, изменив параметр android:orientation на vertical.
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 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="vertical" android:gravity="center_horizontal" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:text="Надпись на заборе" android:layout_width="80dp" android:layout_height="wrap_content" android:gravity="center"/> <Switch android:id="@+id/switcher" android:text="Свет на кухне" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:id="@+id/button" android:text="reboot" android:layout_width="85dp" android:layout_height="wrap_content"/> <ImageView android:id="@+id/imageView" android:layout_width="60dp" android:layout_height="60dp" app:srcCompat="@drawable/dragon"/> </LinearLayout> |
Получилось классно. Более того, центрированные по горизонтали компоненты, идущие друг под другом, выглядят как интересный интерфейс. Такой вариант разметки уже можно использовать в каком-нибудь приложении, привязав его к Activity. А ведь обошлись мы одним LinearLayout, без создания сложных вложенных друг в друга макетов.
Веса компонентов (weights)
Что делать, если хочется задать не точный размер в dp, например, и не wrap_content, не match_parent? Что делать, если нужно задать размер в процентных соотношениях? А если нужно предоставить компоненту всё оставшееся после других место?
LinearLayout дружелюбно помогает справиться с этой задачей. Он позволяет использовать атрибут android:layout_weight для управления относительными размерами внутренних компонентов. Этот атрибут указывает, как много доступного пространства каждый компонент будет занимать в соответствии с его весом. Итак, как указать вес компонента в LinearLayout?
Например, нам нужно сделать текстовое поле и кнопку для подтверждения. Кнопка Button будет иметь фиксированный размер. А вот текстовое поле EditText хотелось бы вытянуть по всей оставшейся ширине. Сделаем это средствами весов компонентов. Внимание: при указании веса компонента нужно занулить его размер в этом направлении. Так как LinearLayout горизонтальный, то занулить для EditText-а нужно ширину, то есть android:layout_width=”0dp”.
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"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="horizontal" android:gravity="center_horizontal" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/editText" android:text="" android:hint="Введите текст..." android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content"/> <Button android:id="@+id/button" android:text="Ок" android:layout_weight="0" android:layout_width="60dp" android:layout_height="60dp"/> </LinearLayout> |
Как видно, всё прошло гладко. Кнопка Button имеет ширину 60dp, а EditText занял всё оставшееся место по ширине. Давайте теперь разберёмся, что произошло, и что означают эти магические 0 и 1.
По умолчанию у каждого добавленного элемента внутри LinearLayout вес равен нулю. То есть свойство android:layout_weight установлено в 0. Значение 0 означает, что компонент занимает ровно столько места, сколько ему требуется для вмещения всего его содержимого. То есть, по сути, как wrap_content. Фактически, для кнопки не обязательно было указывать android:layout_weight=”0″. Ведь именно такое значение было выставлено для неё изначально автоматически. Но я сделала это для наглядности. Теперь, если же установить android:layout_weight в положительное значение, начнётся магия. Число, выставленное в этом параметре, будет использоваться в качестве соотношения с другими компонентами, также имеющими вес больше нуля.
Так как в LinearLayout только 2 компонента, и только один из них – EditText – имеет вес больше нуля, то он занял 100% оставшегося места. В этом случае можно было бы вписать любое целое положительное число в параметр android:layout_weight.
Добавим второй компонент (TextView), который будет конкурировать за свободное место с EditText-ом. Поставим ему вес такой же – 1. Теперь каждый из этих компонентов будет занимать по 1/2 свободного пространства.
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 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="horizontal" android:gravity="fill_vertical" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:text="Oh, jingle bells, jingle bells, Jingle all the way, Oh, what fun it is to ride, In a one horse open sleigh" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" /> <EditText android:id="@+id/editText" android:text="" android:hint="Введите текст..." android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content"/> <Button android:id="@+id/button" android:text="Ок" android:layout_weight="0" android:layout_width="60dp" android:layout_height="60dp"/> </LinearLayout> |
Как полагается, кнопка заняла своё по праву выделенное место. Затем всё оставшееся место поровну поделили между собой TextView и EditText.
Но что, если мы хотим неравенства? Например, выдать побольше жизненного пространства для EditText, урезав его для TextView. Ничего сложного: в таком случае нужно просто задать разные веса. Например, 2 к 5. Это означает, что TextView будет занимать 2/7, а EditText – 5/7 свободного пространства.
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 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/mainLayout" android:orientation="horizontal" android:gravity="fill_vertical" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:text="Oh, jingle bells, jingle bells, Jingle all the way, Oh, what fun it is to ride, In a one horse open sleigh" android:layout_weight="2" android:layout_width="0dp" android:layout_height="wrap_content" /> <EditText android:id="@+id/editText" android:text="" android:hint="Введите текст..." android:layout_weight="5" android:layout_width="0dp" android:layout_height="wrap_content"/> <Button android:id="@+id/button" android:text="Ок" android:layout_weight="0" android:layout_width="60dp" android:layout_height="60dp"/> </LinearLayout> |
В итоге EditText взял на себя дополнительные привилегии, а TextView немного сжался. Вы можете задавать любые другие соотношения своим компонентам. Главное – не забывайте для компонента устанавливать в 0 размер направления, соответствующего ориентации LinearLayout.
Что мы имеем на выходе? LinearLayout подходит для создания простых макетов, где элементы должны быть выровнены в одной линии. В частности, он хорошо подходит для списков, кнопок, текстовых полей и других базовых элементов пользовательского интерфейса. Однако, если вам нужно более замысловатое расположение элементов с различными ограничениями и выравниванием, то вам пригодятся более сложные макеты, такие как ConstraintLayout.