- Полный список
- Экраны
- Layout width и Layout height
- Абсолютные значения:
- Константы
- Layout gravity
- Layout margin
- Стили
- Использование layout_gravity = «bottom» для размещения внизу LinearLayout
- LinearLayout
- Общая информация
- Примеры
- Градиентный фон
- Меняем фон программно
- Программная анимация компоновки
- Отключаем выравнивание по базовой линии
- Разделители
- Программное создание разметки LinearLayout
Полный список
На этом уроке мы:
— разбираемся в характеристиках экрана
— рассматриваем layout параметры (высота, ширина, отступ, гравитация, вес)
Экраны
Для начала немного теории по экранам. Экран имеет такие физические характеристики как диагональ и разрешение. Диагональ – это расстояние между противоположными углами экрана, обычно измеряется в дюймах. Разрешение – кол-во точек по горизонтали и вертикали, которое экран способен отобразить, измеряется в пикселах.
Возьмем в качестве примера экран смартфона HTC Desire. Диагональ = 3,7 дюйма, разрешение = 800х480 пикселей.
Кол-во пикселей в одном дюйме называется dpi (dot per inch). Узнаем чему равно dpi в данном случае, вспомнив классику: c 2 = a 2 + b 2 , где с – кол-во пикселей по диагонали, т.е. вмещаемое в 3,7 дюйма. a и b – стороны экрана.
c = 3,7 * dpi
(3,7 * dpi) 2 = 480 2 + 800 2
dpi 2 = 870400 / 13,69 = 63579
dpi = 252. Т.е. в одном дюйме экрана помещается ряд из 252 пикселей.
Возвращаемся к теме урока. Рассмотрим подробно следующие параметры View элементов
Layout width и Layout height
Про ширину (layout_width) и высоту (layout_height) мы уже немного говорили на прошлом уроке. Мы можем указывать для них абсолютные значения, а можем использовать константы. Разберем подробнее эти возможности.
Абсолютные значения:
Используются следующие единицы измерения (ЕИ):
dp или dip — Density-independent Pixels. Абстрактная ЕИ, позволяющая приложениям выглядеть одинаково на различных экранах и разрешениях.
sp — Scale-independent Pixels. То же, что и dp, только используется для размеров шрифта в View элементах
pt — 1/72 дюйма, определяется по физическому размеру экрана. Эта ЕИ из типографии.
px – пиксел, не рекомендуется использовать т.к. на разных экранах приложение будет выглядеть по-разному.
mm – миллиметр, определяется по физическому размеру экрана
in – дюйм, определяется по физическому размеру экрана
Подробней о различиях и соотношениях между этими ЕИ вы можете прочесть в этом материале сайта.
Константы
match_parent (fill_parent) – означает, что элемент займет всю доступную ему в родительском элементе ширину/высоту.
wrap_content – ширина/высота элемента будет определяться его содержимым
Project name: P0072_LayoutProp
Build Target: Android 2.3.3
Application name: LayoutProp
Package name: ru.startandroid.develop.layoutprop
Create Activity: MainActivity
Открываем main.xml. Настроим корневой LinearLayout на горизонтальную ориентацию, удалим TextView, и добавим Button с шириной и высотой равной wrap_content. Она отображается на экране и ее ширина соответствует тексту на ней.
Изменим текст с «Button» на «Button with text», сохраним и посмотрим на экран.
Кнопка стала шире, т.к. ширина определяется по содержимому. Если же мы сейчас явно укажем ей ширину 250 dp, то кнопка растянется независимо от содержимого.
Теперь сделаем ширину равной match_parent. Кнопка растянулась на всю ширину родителя, т.е. LinearLayout. А LinearLayout в свою очередь занимет всю ширину экрана.
Если у нас родитель содержит несколько элементов и мы хотим, чтобы они заняли все пространство необходимо использовать параметр Layout weight – вес. Свободное пространство распределяется между элементами пропорционально их weight-значениям.
Изменим текст нашей кнопки на B1 и добавим ей соседа по LinearLayout – вторую кнопку с текстом B2. Ширину для обоих поставьте wrap_content
Займемся дележом. Если мы хотим, чтобы кнопки поделили пространство родителя поровну – то для обеих укажем weight = 1. В этом случае кнопки равны по ширине.
Обратите внимание, что не используются единицы измерения, указываются просто числа.
Если нужно, чтобы B1 занимала четверть, а B2 три четверти свободного пространства, то проставляем weight = 1 для B1 и weight = 3 для B2.
Кол-во элементов может быть любым. Добавим еще кнопку с текстом B3, weight = 2 и width = wrap_content.
xml-код получившегося экрана:
Теперь для B2 и B3 укажите weight = 0. Они больше не претендуют на свободное пространство и занимают ширину по содержимому, а B1 забирает все себе.
Разумеется, все выше сказанное применимо и для параметра высоты — height.
При использовании weight вы можете указать значение height или width = 0dp. В этом случае не будет учитываться содержимое элементов и результат будет более соответствующий коэффициентам веса.
Layout gravity
Параметр layout_gravity аналогичен выравниванию из Word или Excel. Удобнее всего продемонстрировать его с использованием FrameLayout. Я не описывал этот Layout на прошлом уроке, т.к. он совсем простой. Все помещаемые в него элементы он по умолчанию помещает в левый верхний угол и никак их не выстраивает. Нам это очень подходит для демонстрации настроек выравнивания.
Создадим grlayout.xml:
На экране видим:
Для наглядности текст кнопки отображает ее свойства. Все очевидно и несложно.
Я честно пытался понять зачем нужны значения gravity fill_* и clip_*, но так и не понял. То, что написано про них в хелпе у меня не работает. Если у вас есть сведения по этому поводу – пишите в каменты.
Layout margin
Параметры margin полностью аналогичны margin из html. Это отступ. Он может быть со всех сторон сразу, либо только с необходимых сторон. Продемонстрируем это на примере TableLayout. Создадим marginlayout.xml и нарисуем таблицу три на три с кнопками.
И на кнопке в центре будем экспериментировать.
margin = 50 dp
Вокруг кнопки со всех сторон образовался отступ = 50 dp.
margin left = 10 dp
margin top = 20 dp
Отступ слева и сверху.
margin right = 30 dp
margin bottom = 40 dp
Отступ справа и снизу.
Урок получился большой, но полезный. Думаю, это был последний урок дизайна, моделирования и верстки и дальше мы уже начнем кодить.
Стили
Если кто использовал HTML, то наверняка слышали про каскадные стили — CSS. Стили позволяют вам группировать атрибуты элементов (кнопок, таблиц, параграфов и т.д.). Далее вы просто применяете к элементам стили, и элемент рисуется с учетом всех атрибутов стиля. И нет необходимости повторять несколько раз один и тот же код для элементов, которые должны выглядеть одинаково. Особенно это удобно в случае изменения атрибутов. Вы просто меняете один раз стиль и все элементы с этим стилем меняются.
В Android тоже есть стили и они имеют точно такое же назначение. Если у вас есть несколько элементов и вам надо, чтобы они выглядели одинаково, то вы просто создаете один стиль и применяете его к нужным элементам. В принципе, вы пока можете не заморачиваться этим и начать использовать стили, когда наберетесь опыта. Ну а тем кому это интересно прямо сейчас — прошу в эту ветку нашего форума. Пользователь icamys на примере подробно разъясняет как использовать стили.
На следующем уроке:
— научимся обращаться к View-элементам из кода и менять их свойства
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Использование layout_gravity = «bottom» для размещения внизу LinearLayout
Я хотел бы разместить макет в нижней части LinearLayout, но я не могу заставить его работать. Я знаю, что я могу использовать RelativeLayout для этого, но я должен использовать LinearLayout, не так ли?
EDIT: На самом деле это более запутанно, чем я думал. Схема ниже упрощена. На самом деле, я использую фрагменты на устройстве pre-3.0 с уровнем совместимости.
Я использовал Hierarchy Viewer для изучения того, что происходит, и обнаружил, что в мой макет добавлен файл android.support.v4.app.NoSaveStateFrameLayout, и этот макет имеет layout_height, установленный на wrap_content. Кажется, это то, что вызывает мою проблему, но я еще не понял, как это исправить.
В частности, почему это не работает? Разве расположение макета не должно располагаться внизу?
Кстати, изменение layout_height для fill_parent или установка layout_weight тоже не работают. Я просто хочу лучше понять, что происходит, потому что ясно, что я пропускаю что-то важное. Благодарю.
Прежде всего, хороший вопрос.
Android ведет себя, мы можем сказать, что странно в такой ситуации.
Если вы выбрали горизонтальную ориентацию родительского линейного макета, тогда вы можете установить его дочерний компонент внизу, установив его layoug_gravity = bottom. Предположим, что вы добавили 2 текстовых вида в горизонтальном линейном макете, а layout_gravity второго текста – снизу, тогда он будет установлен снизу, но он работает так, как он установлен снизу в другом столбце, а затем в первом текстовом представлении. ПРИМЕЧАНИЕ . Вы можете установить layout_gravity = «left» или «right» textview, когда его родительский linearlayout является горизонтальным, но вы не можете увидеть его результат.
Противоположно, если вы выбрали вертикальную ориентацию parent linearlayout вертикальной, вы можете установить ее дочерний компонент слева или справа, используя layout_gravity. Но второе текстовое изображение будет показано в следующей строке с левой или правой степенью тяжести, как вы уже установили. ПРИМЕЧАНИЕ. Вы можете установить layout_gravity = «top» или «bottom», если его линейный макет вертикальный, но вы не можете увидеть его результат.
Постарайтесь создать образец xml-дизайна, как я уже сказал выше, чтобы вы лучше поняли.
Удивительно, но факт. Попытайтесь понять это поведение. 🙂
Поэтому я решил проблему. Это двухкомпонентное решение:
Во-первых, способ сделать это без использования LinearLayout – обеспечить вес элемента выше, чтобы он занимал все пустое пространство. Кстати, вы можете увидеть этот пример в демонстрациях API: http://developer.android.com/resources/samples/ApiDemos/res/layout/linear_layout_3.html
Это само по себе не решило мою проблему, поскольку у меня был NoSaveStateFrameLayout с layout_width = «wrap_content» в качестве родительского представления, и поэтому мне нужно было сначала получить это исправление. Я использую код на основе замечательного приложения ввода / вывода Google , и когда я искал код для NoSaveStateFrameLayout, я нашел это:
Спасибо за замечательный комментарий Google . Я добавил это в свой источник, и все отлично поработало!
Мораль истории: Hierarchy Viewer и комментарии – ваши друзья.
Просто добавьте пробел между тем, что вы хотите внизу, и всем остальным:
LinearLayout будет просто складывать вещи по мере их размещения. Поскольку он является вертикальным, он будет размещать предметы один за другим по вертикали. Можете ли вы изменить андроид: гравитация линейногоLayout, а не layout_gravity вложенного и посмотреть, работает ли это.
RelativeLayout, конечно, должен быть первым, но вы заявили, что не хотите этого делать. Есть ли причина для этого?
Источник
LinearLayout
Общая информация
В студии макет LinearLayout представлен двумя вариантами — Horizontal и Vertical. Макет LinearLayout выравнивает все дочерние объекты в одном направлении — вертикально или горизонтально. Направление задается при помощи атрибута ориентации android:orientation:
Все дочерние элементы помещаются в стек один за другим, так что вертикальный список компонентов будет иметь только один дочерний элемент в ряду независимо от того, насколько широким он является. Горизонтальное расположение списка будет размещать элементы в одну строку с высотой, равной высоте самого высокого дочернего элемента списка.
В этом примере используются два способа размещения элементов TextView: по горизонтали и по вертикали.
У разметки LinearLayout есть интересный атрибут android:layout_weight, который назначает индивидуальный вес для дочернего элемента. Этот атрибут определяет «важность» представления и позволяет этому элементу расширяться, чтобы заполнить любое оставшееся пространство в родительском представлении. Заданный по умолчанию вес является нулевым.
Например, если есть три текстовых поля, и двум из них объявлен вес со значением 1, в то время как другому не даётся никакого веса (0), третье текстовое поле без веса не будет расширяться и займёт область, определяемую размером текста, отображаемого этим полем. Другие два расширятся одинаково, чтобы заполнить остаток пространства, не занятого третьим полем. Если третьему полю присвоить вес 2 (вместо 0), это поле будет объявлено как «более важное», чем два других, так что третье поле получит 50% общего пространства, в то время как первые два получат по 25% общего пространства.
Также можно указать атрибут android:weightSum. Если атрибуту присвоить значение 100, то можно указывать вес дочерних элементов в удобном виде, как в процентах. Такой способ широко используется веб-мастерами при вёрстке.
Создадим простейшую разметку таким образом, чтобы дочерний элемент занимал половину родительского контейнера:
Примеры
Рассмотрим возможности LinearLayout на примерах.
Создадим 7 текстовых меток и присвоим им цвета радуги. Расположим их друг за другом. Получим следующий результат
Отцентрируем текст в TextView при помощи свойства Gravity, установив значение Center. Аналогично поступим и с LinearLayout, чтобы выровнять по центру текстовые метки.
Цветные полоски получились слишком узкими. Расширим их за счет увеличения размера шрифта (TextSize) у текстовых меток.
Стало чуть лучше, но все равно пропадает много свободного пространства. Совсем не хочется видеть чёрный цвет сверху и снизу. Здесь нам придёт на помощь свойство Layout weight. Так как число 7 не совсем удобное для деления, то поступим следующим образом. Пяти элементам присвоим вес 0.14, а двум — 0.15, что в сумме даст 1.0. Теперь элементы равномерно заполнят весь экран.
Если мы хотим сделать плавное увеличение высоты полоски, то вес нужно распределить таким образом: 0.08, 0.10, 0.12, 0.14, 0.16, 0.18, 0.22.
Чем хорош этот способ? Мы не привязываемся к точным размерам, а позволяем системе самой расчитывать равномерное распределение элементов по экрану. Если в Eclipse вы выберите режим Landscape, то экран будет выводиться в альбомном режиме и при этом элементы по-прежнему будет равномерно распределены.
Градиентный фон
Если вам нужен градиентный фон для LinearLayout, то создайте в папке res/drawable xml-файл, например, gradient.xml:
Далее остаётся только прописать файл в свойстве Background:
Меняем фон программно
Чтобы программно сменить фоновый цвет у LinearLayout, нужно вызвать метод setBackgroundColor(). Пример изменения фона можно найти в статье Android::Класс android.graphics.Color.
Программная анимация компоновки
Хочу показать один пример программной анимации. Не знаю, имеет ли пример практическую ценность, но для общего развития не помешает. Добавьте в шаблон LinearLayout несколько кнопок, текстовых полей и других элементов на ваше усмотрение. Далее пишем код для обработчика щелчка кнопки и вспомогательный класс для анимации:
Когда вы щелкните на кнопке, то LinearLayout будет плавно увеличиваться в размерах. Данный приём можно использовать не только к компоновке, но и к любому объекту View.
Отключаем выравнивание по базовой линии
Допустим, у вас есть следующая разметка:
Если посмотрим, что получилось, то увидим, что средняя кнопка опустилась вниз.
Строго говоря, разметка составлена не совсем правильно, используя жёстко установленные величины. Но будем считать, что такой код достался от другого программиста и заказчик не хочет его кардинально менять. Причина такого поведения кнопки в том, что по умолчанию Android пытается выравнивать элементы по некой базовой линии. А средняя кнопка имеет слишком длинный текст и она вот таким причудливым образом сместилась вниз. Можно попробовать использовать свойства gravity, но можно поступить проще. Добавьте атрибут android:baselineAligned=»false» к LinearLayout и все три кнопки будут аккуратно находиться на одной линии. Имейте в виду, может пригодится.
Разделители
Начиная с API 11, у LinearLayout появился новый атрибут android:divider, позволяющий задать графический разделитель между кнопками. Также нужно явно включить использование разделителей через атрибут android:showDividers, в котором можно указать, каким образом использовать разделители — только в середине, в начале, в конце — можно комбинировать эти значения.
Создадим в папке res/drawable файл separator.xml:
Разметка для активности:
Разделители могут оказаться полезными. В статье Grid Spacing on Android показан хороший пример на эту тему.
Допустим, мы хотим вывести в ряд три кнопки под каким-то компонентом, например, логотипом компании. Разметка может быть следующей.
Вместо @dimen/spacing_medium можете подставить 8dp, а цвета придумать свои, если будете проверять пример самостоятельно.
Видно, что напрашивается дизайн в виде сетки. Отсутствие пространства между кнопками может создать неудобства у пользователя. Добавим их. У контейнера @id/buttons_container добавим android:layout_marginTop=»@dimen/spacing_medium», а у первой и второй кнопки добавим android:layout_marginRight=»@dimen/spacing_medium» (напомню, можно использовать 8dp)
Всё отлично работает до того момента, если нам понадобится программно убрать с экрана третью кнопку. Сделать это можно через View.GONE. И что мы увидим?
Теперь вторая кнопка не выровнена по правому краю. Некрасиво. Очень плохим решением станет программный пересчёт всех величин, чтобы выровнять компоненты. Как вариант, использовать другой тип разметки, например, GridLayout. Но у него есть свои проблемы с отступами и вам будет тяжело добиться нужного результата.
Проблема красиво решается с помощью упомянутых выше разделителей. Создадим в папке res/drawable файл spacer_medium.xml:
Теперь кнопки всегда будут аккуратно выравнены по краям, независимо от их количества — две или три.
Программное создание разметки LinearLayout
В некоторых случаях может понадобиться создать LinearLayout программным способом. Сначала создаётся объект LayoutParams, на его основе создаётся LinearLayout, а позже в него добавляются дочерние компоненты.
Также программно можно управлять настройками LinearLayout через тот же объект LayoutParams. Разместите кнопку с обработчиком щелчка.
Каждый щелчок на кнопке будет увеличивать отступ на пять единиц и кнопка будет смещаться в сторону. Интересно, что если убрать TextView, то кнопка перестаёт двигаться. Причина мне неизвестна.
Источник