Android – создание простого пользовательского интерфейса
Создание простого пользовательского интерфейса в android приложении
Графический интерфейс андроид приложений строится на иерархии из элементов двух типов: View и ViewGroup. Элементами типа View являются любые дочерние элементы пользовательского интерфейса (UI widgets), такие как кнопка (button), поле для ввода и пр. ViewGroup – это невидимый контейнер графических элементов (вышеупомянутых view), определяющий их размещение на интерфейсе. Это может быть вертикальный, горизонтальный список или таблицы элементов.. Один ViewGroup может содержать множество view и другие ViewGroup. Оперируя различными графическими элементами и контейнерами эл-в можно создавать интерфейсы.
Иерархия view и viewGroup при построении пользовательского интерфейса в android
Перейдем от теории к практике, изменим стандартный экран приложения (HelloWorld), который отображается при запуске (ну или можете создать новое приложение 😉 ). Откроем текущее отображение экрана (файл activity_main.xml из директории res/layout).
Создание LinearLaout
Обратите внимание, что перед Вами открылся визуальный редактор интерфейса (Graphical layout). Все действия можно выполнять тут, а можно перейти в режим отображения кода ( activity_main.xml – слева внизу под набором доступных элементов). Я использую оба варианта. Как по мне удобно накидать необходимых элементов с помощью графического редактора а потом уже точечно по необходимости подправить каждый элемент в коде. Выбирайте удобный для Вас способ, но настоятельно рекомендую разобраться с тем, что пишется в коде.
По умолчанию на форме находится RelativeLayout (ViewGrop) и текстовое поле (view). Подробно о каждом контейнере поговорим позже, сейчас удалим текст с экрана и поменяем стандартный Layout на LinearLaout, в который добавим поле android:orientation и установим значение «horizontal» .
LinearLaout – это ViewGrop, который отображает дочерние элементы один за другим в вертикальном или горизонтальном формате, в зависимости от значения поля android:orientation . Используя линейный контейнер графические элементы на экране будут отображены в том же порядке, в котором они находятся в xml файле.
Поля android:layout_width и android:layout_height должны быть указаны для всех графических элементах для указания их размера. Учитывая, что наш LinearLaout это корневой элемент интерфейса, мы указываем ему заполнить все пространство экрана, устанавливая width и height равными «match_parent» .
Создание простого интерфейса в android с LinearLayout
Добавление текстового поля
Далее добавим в интерфейс текстовое поле для ввода (элемент EditText ). Как и при использовании любого другого графического элемента, необходимо указать некоторые основные свойства данного объекта. В нашем случае элемент задается следующим кодом:
Добавление поля для ввода текста в android интерфейс
В этом случае свойства android:layout_width и android:layout_height заданы как «wrap_content» , указывая что элементы должны быть такого размера, чтобы заполнить содержимое отображения. Если Вы укажите значение «match_parent» , то поле для ввода заполнит весь экран т.к. указано что оно должно растянуться до размера своего предка – LinearLayout .
Свойство android:id – это уникальный идентификатор для графического элемента. Он будет использоваться чтобы обратиться к элементу из кода программы, например, для чтения значения.
Знак собачки ( @ ) необходим, когда идет обращение к любому ресурсу из XML. Он следует после указания типа ресурса ( id в текущем случае), слэш, потом имя ресурса ( edit_message ).
Знак плюса ( + ) необходим только в случае первого объявления ID ресурса. Когда происходит компиляция, SDK tools использует ID чтобы создать новый ресурс в файле gen/R.java . В дальнейшем при использовании идентификатора не нужно указывать знак плюса.
Свойство android:hint – это значение той строки, что будет отображаться в поле для ввода по умолчанию (когда оно пустое). Вместо того, чтобы задавать строку в файле разметки, используется запись «@string/edit_message», кот. говорит о том, что значение строки берется с файла ресурсов строк. “edit_message” – это ключ, по которому будет получено значение строки. Т.к. мы обращаемся к конкретному ресурсу (а не просто идентификатору) нет необходимости использовать знак плюса. В данный момент, из-за того, что строка в файле ресурсов еще не объявлена, компилятор выдает ошибку. Исправим ее, добавив соответствующий ресурс!
Добавление строки в файл ресурсов (strings.xml)
Все строки, что используются в интерфейсе должны быть объявлены в отдельном файле ресурсов. В дальнейшем такой подход значительно упростит изменение текстов приложения и добавления локализаций (других языков, кот будет поддерживать приложение).
По умолчанию, в проекте уже есть ресурсный файл со строками: res/values/strings.xml . Добавьте новую строку с именем «edit_message» и значением “Enter a message.” Так же Вы можете удалить строку “hello_world”. И можно сразу добавить строку, которую мы вскоре будем использовать для кнопки: “Send” с ключом «button_send» .
В результате файл strings.xml выглядит следующим образом (в режиме кода! переключатель слева внизу ;)):
android resources – strings.xml
Добавление кнопки на экран приложения
Далее добавим на форму кнопку, следующую за полем для ввода. Свойства height и width установлены в «wrap_content» , что говорит о том, что кнопка будет размером, необходимым для текста на кнопке. Атрибут android:id не установлен т.к. он не будет использоваться в коде приложения.
В результате получается следующий интерфейс:
Создаем простой android интерфейс
Размещение поля для ввода по всем ширине экрана
Оптимизируем его немного: растянем поле для ввода по ширине экрана. В данный момент ширина обоих графических элементов установлена в «wrap_content» . Для кнопки данное значение нормально, но для поля для ввода – не очень т.к. пользователь может ввести строку длиннее, чем поместиться в элемент (можете запустить сейчас приложение и попробовать ввести длинное значение 😉 ).
Итак, чтобы растянуть поле на неиспользуемую часть экрана в LinearLayout (в других контейнерах невозможно указать вес для графического элемента! Там используются другие свойства), необходимо указать атрибут weight ( android:layout_weight ).
Свойство weight это число, указывающее на то, сколько оставшегося пространства будет занимать один элемент на экране среди множества других. Т.е. фактически задаются пропорции занимаего пространства каждым графическим элементом. К примеру, есть 2 элемента, у одного вес равен 2, у второго – 1. на экране первый элемент будет занимать 2/3 всего пространства а второй – оставшиеся место.
По умолчанию вес каждого элемента равен нулю. Если для любого элемента указать значение веса больше нуля, этот элемент растянется по “свободному” пространству экрана. Мы так и сделаем, указав полю ввода вес равный одному. В результате форма должны быть представлена следующим кодом:
Код простого интерфейса android приложения
А сам интерфейс будет выглядит вот так:
Простой пользовательский интерфейс andoird приложения
Т.к. редактировался главная и единственная форма приложения, ее Вы и увидите при запуске приложения ;).
Источник
Основы создания интерфейса
Введение в создание интерфейса
Графический интерфейс пользователя представляет собой иерархию объектов android.view.View и android.view.ViewGroup . Каждый объект ViewGroup представляет контейнер, который содержит и упорядочивает дочерние объекты View . В частности, к контейнерам относят такие элементы, как RelativeLayout, LinearLayout, GridLayout, ConstraintLayout и ряд других.
Простые объекты View представляют собой элементы управления и прочие виджеты, например, кнопки, текстовые поля и т.д., через которые пользователь взаимодействует с программой:
Большинство визуальных элементов, наследующихся от класса View, такие как кнопки, текстовые поля и другие, располагаются в пакете android.widget
При определении визуального у нас есть три стратегии:
Создать элементы управления программно в коде java
Объявить элементы интерфейса в XML
Сочетание обоих способов — базовые элементы разметки определить в XML, а остальные добавлять во время выполнения
Сначала рассмотрим первую стратегию — определение интерейса в коде Java.
Создание интерфейса в коде java
Для работы с визуальными элементами создадим новый проект. В качестве шаблона проекта выберем Empty Activity :
Пусть он будет называться ViewsApp:
И после создания проекта два основных файла, которые будут нас интересовать при создании визуального интерфейса — это класс MainActivity и определение интерфейса для этой activity в файле activity_main.xml .
Определим в классе MainActivity простейший интерфейс:
При создании виджетов в коде Java применяется их конструктор, в который передается контекст данного виджета, а точнее объект android.content.Context , в качестве которого выступает текущий класс MainActivity.
Здесь весь интерфейс представлен элементом TextView, которое предназначено для выводa текста. С помощью методов, которые, как правило, начинаются на set , можно установить различные свойства TextView. Например, в данном случае метод setText() устанавливает текст в поле, а setTextSize() задает высоту шрифта.
Для установки элемента в качестве интерфейса приложения в коде Activity вызывается метод setContentView() , в который передается визуальный элемент.
Если мы запустим приложение, то получим следующий визуальный интерфейс:
Подобным образом мы можем создавать более сложные интерейсы. Например, TextView, вложенный в ConstraintLayout:
Для каждого контейнера конкретные действия по добавлению и позиционированию в нем элемента могут отличаться. В данном случае контейнеров выступает класс ConstraintLayout, поэтому для определения позиционирования и размеров элемента необходимо создать объект ConstraintLayout.LayoutParams . (Для LinearLayout это соответственно будет LinearLayout.LayoutParams, а для RelativeLayout — RelativeLayout.LayoutParams и т.д.). Этот объект инициализируется двумя параметрами: шириной и высотой. Для указания ширины и высоты можно использовать константу ViewGroup.LayoutParams.WRAP_CONTENT , которая устанавливает размеры элемента, необходимые для размещения а экране его содержимого.
Далее определяется позиционирование. В зависимости от типа контейнера набор устанавливаемых свойств может отличаться. Так, строка кода
указывает, что левая граница элемента будет выравниваться по левой ганице контейнера.
указывает, что верхняя граница элемента будет выравниваться по верхней ганице контейнера. В итоге элемент будет размещен в левом верхнем углу ConstraintLayout.
Для установки всех этих значений для конкретного элемента (TextView) в его метод setLayoutParams() передается объект ViewGroup.LayoutParams (или один из его наследников, например, ConstraintLayout.LayoutParams).
Все классы контейнеров, которые наследуются от android.view.ViewGroup (RelativeLayout, LinearLayout, GridLayout, ConstraintLayout и т.д.), имеют метод void addView(android.view.View child) , который позволяет добавить в контейнер другой элемент — обычный виджет типа TextView или другой контейнер. И в данном случае посредством данного метода TextView добавляется в ConstraintLayout:
Опять же отмечу, что для конкретного контейнера конкретные действия могут отличаться, но как правило для всех характерно три этапа:
Создание объекта ViewGroup.LayoutParams и установка его свойств
Передача объекта ViewGroup.LayoutParams в метод setLayoutParams() элемента
Передача элемента для добавления в метод addView() объекта контейнера
Хотя мы можем использовать подобный подход, в то же время более оптимально определять визуальный интерейс в файлах xml, а всю связанную логику определять в классе activity. Тем самым мы достигнем разграничения интерфейса и логики приложения, их легче будет разрабатывать и впоследствии модифицировать. И в следующей теме мы это рассмотрим.
Источник
Jetpack Compose — как легко построить UI на Android
В июле этого года вместе с Android Studio Arctic Fox вышла одна из долгожданных библиотек — Jetpack Compose. Она позволяет создавать пользовательский интерфейс в декларативном стиле и обещает быть революцией в построении UI.
Разбираемся, так ли это на самом деле, какие у библиотеки преимущества и недостатки. Подробности — в статье.
Преимущества Jetpack Compose
Jetpack Compose — это набор инструментов для разработки UI в Android-приложении. Он призван ускорить и упростить разработку пользовательского интерфейса, избавить от лишнего кода и соединить модель реактивного программирования с лаконичностью Kotlin.
Сразу с места в карьер — какие есть преимущества у библиотеки:
1. Меньше кода. Jetpack Compose позволяет писать меньше кода, а значит разработчик может больше фокусироваться на проблеме, с меньшим количеством тестов и дебага, а значит и багов.
2. Интуитивно понятный. Compose использует декларативный API — разработчику нужно лишь сказать, что сделать, а все остальное ляжет на плечи библиотеки.
3. Удобство внедрения. Compose совместим с любым существующим кодом. Например, можно вызвать Compose-код из вьюх (view) и, наоборот, вьюхи из Compose. Многие библиотеки вроде Jetpack Navigation, ViewModel и Coroutines уже адаптированы под Compose, что позволяет сравнительно быстро внедрить его в свой код. Кроме того, Android Studio Arctic Fox поддерживает превью создаваемых вьюх.
4. Имеет обширный инструментарий. Jetpack Compose позволяет создавать красивые приложения с прямым доступом к Android Platform API и build-in поддержкой Material Design, тёмной темы, анимаций и других крутых штук.
Далее пройдёмся по основным аспектам библиотеки и посмотрим, как сильно повышается производительность приложения.
Подключение к проекту
Чтобы подключить Jetpack Compose к проекту, необходимо указать некоторые строки кода в своем build.gradle.
В рутовом объявим переменную с версией Compose:
Здесь мы указываем, что в проекте будем использовать Jetpack Compose и объявляем необходимые зависимости (подробнее про зависимости можно почитать в официальном гайде).
Дальше всё просто. В активити (activity) объявлем Composable-функцию, строим иерархию вьюх с указанием необходимых атрибутов и смотрим результат.
Пройдемся по коду. Я написал две реализации вёрсток различной сложности:
1. Простая реализация
Добавляет TextView в вёрстку с текстом с конкатенацией Hello и аргумента, переданного в Greeting.
Важно отметить, что имена Composable-функций начинаются с заглавной буквы. Это соглашение по наименованию функций, поэтому если писать со строчной, то студия будет подсвечивать неверный нейминг.
2. Более сложная реализация
Этот вариант представляет собой скролящийся экран, который содержит изображение, текст и кнопку. Рассмотрим некоторые особенности:
Необходимо объявить Scroll State. Только не обычный, а тот, который позволяет сохранять состояние скролла сквозь рекомпозицию — rememberScrollState().
Column представляет собой ViewGroup с вертикальным расположением элементов.
Modifier позволяет управлять атрибутами, добавлять декорации и поведение к вьюхам.
Остальное интуитивно понятно. И это как раз одна из ключевых особенностей Jetpack Compose — даже если вы не использовали библиотеку ранее, то всё равно с ней разберётесь.
Добавить вьюхи в активити можно через extension setContent <>, например:
В общем-то, создание UI выглядит действительно просто. Теперь определим, насколько сильно оптимизируется приложение и как быстро пользователь увидит окончательный экран.
Для тестирования воспользуемся библиотекой Jetpack Benchmark, о которой, кстати, тоже рассказывали в отдельной статье. Код теста выглядит так:
Протестируем три версии установки вьюхи в активити:
При передаче ресурса в setContentView.
При передаче вьюхи в setContentView.
Итоги тестирования можно посмотреть в таблице: левый столбец — название теста, правый — время на выполнение:
Источник