Здесь мы разберем пользовательский интерфейс шаблона, созданного в 7-м уроке, очистим его от лишнего кода, чтобы в дальнейшем вы могли использовать шаблон для написания ваших демо-приложений.
Теперь, зная из чего создается пользовательский интерфейс, давайте разберем стандартный шаблон, который мы создали в 7-м уроке.
Начнем с окна (Win). Win – это корневой элемент экрана. Он будет родителем для остальных компонентов.
Окно создается с помощью функции:
elm_win_util_standard_add(char *name, char *title);
Эта функция производная от функции:
elm_win_add(NULL, char *name, ELM_WIN_BASIC);
которая создает стандартное окно с заданным именем. Отличие первой функции от второй состоит в том, что она создает окно с уже добавленным виджетом фона и присваивает окну заголовок (title). Тем не менее, эти два параметра не актуальны для Wearable профиля, их можно проигнорировать, передав в функцию: (NULL, NULL). Для стандартного окна родитель не нужен, поэтому этот параметр у нас NULL.
Теперь нужно указать, что окно не будет содержать в себе конформант:
elm_win_conformant_set(ad->win, EINA_TRUE);
Опция
elm_win_autodel_set(ad->win, EINA_TRUE);
означает, что объект окно будет автоматически удален при закрытии приложения, таким образом, для освобождения ресурсов не нужно будет явно вызывать удаление окна.
Если функция elm_win_wm_rotation_supported_get(ad->win) возвращает истину, это означает, что оконный менеджер поддерживает поворот окна. И можно прописать как оконному менеджеру производить поворот окна. Следующими строками дайте команду менеджеру поворачивать окно на 90°, количество доступных поворотов – 4.
if (elm_win_wm_rotation_supported_get(ad->win))
{
int rots[4] = { 0, 90, 180, 270 };
elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
}
Таким образом, за полный круг окно может сменить свою ориентацию на 0°, 90°, 180° и 270°. Что касается часов, поворот экрана возможен только если они находятся на подставке, на зарядке.
Объект окно, как и объекты большинства других компонентов экрана, имеет тип Evas_Object. Всем таким объектам можно зарегистрировать или добавить функции обратного вызова, обрабатывающее различные события, с которыми мы будем знакомить вас постепенно. Первый метод, который мы рассмотрим, — это функция-обработчик удаления окна. Обратите внимание, что функция:
evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);
представленная в шаблоне, не подходит для приложения, написанного для Wearable устройства. Это обусловлено тем, что когда пользователь нажимает системную кнопку "X" — закрыть, находящуюся на панели самого окна, этот смарт-колбэк срабатывает в десктопной версии EFL приложений. Скорее всего, эта функция была неосторожно скопирована с enlightenment документации EFL для десктопных приложений. Поэтому с примерами, представленными на developer.tizen.org, нужно быть осторожнее.
Вызов
eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad);
регистрирует функцию-обработчик нажатия аппаратной кнопки Назад.
Сигнатура колбека следующая:
typedef void (*Eext_Event_Cb)(void *data, Evas_Object *obj, void *event_info);
По нажатию на кнопку "Назад" мы сворачиваем окно.
static void
win_back_cb(void *data, Evas_Object *obj, void *event_info)
{
appdata_s *ad = data;
/* Let window go to hide state. */
elm_win_lower(ad->win);
}
Если необходимо закрыть приложение, а не просто свернуть окно, то можно вызвать функцию ui_app_exit(), которая прерывает главный цикл приложения и оно заканчивает свою работу.
Контейнер из библиотеки Elementary. Конформант состоит из нескольких частей: контент (занимает все пространство, в эту область будет помещен пользовательский интерфейс), системные индикатор (накладывается сверху на контент) и виртуальная клавиатура. Таким образом, если вы будете использовать в вашем приложении системную клавиатуру, можете быть уверены, что она отобразиться поверх всего вашего пользовательского интерфейса. На схеме ниже показана компоновка конформанта.
Область для индикатора в Wearable профиле не используется, что, вероятно, обусловлено небольшим размером экрана. Область контента можно заполнить с помощью метода elm_object_content_set(...). Создается конформант следующим вызовом:
ad->conform = elm_conformant_add(ad->win);_object_content_set(...).
Также мы можем дать рекомендации по поводу размеров конформанта. Следующая функция прописывает, что конформант будет занимать все выделенное ему пространство по горизонтали и вертикали.
evas_object_size_hint_weight_set(ui->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
Строка
elm_win_resize_object_add(ad->win, ad->conform);
означает, что окно обуславливает размеры конформанта, то есть размеры конформанта изменяются так, чтобы соответствовать размерам окна.
Конформант отображается следующим вызовом:
evas_object_show(ad->conform);
Текстовый виджет (Label) — это виджет для отображения текста. Для форматирования текста лейбл использует HTML-подобный язык разметки. Следующими строками мы создадим лейб, добавим в него по центру текст "Hello Tizen". Далее указывается, что виджет будет заполнять все предоставленное ему пространство, в данном случае, это область контента конформанта, поскольку здесь лейбл добавляется как содержимое конформанта.
ad->label = elm_label_add(ad->conform);
elm_object_text_set(ui->label, "Hello Tizen");
evas_object_size_hint_weight_set(ad->label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_content_set(ad->conform, ad->label).
Наконец, отображаем окно, после того как отображены все входящие в него объекты.
evas_object_show(ad->win);
В документации настоятельно рекомендуется отображать окно только после того, как был создан весь базовый графический интерфейс. Этот способ более продуктивен, поскольку, при старте приложения, позволяет избежать выполнения лишних операций системой.
Далее вы найдете переформатированный код из шаблона приложения, чтобы в следующих уроках его было удобнее использовать при создании различных демо-приложений. Из проекта был удален заголовочный файл, теперь весь начальный код находиться в main.c файле. Также, для ясности, были добавлены комментарии. Редактированный код изложен ниже. Полный исходный код вы можете скачать здесь WearUITemplate.
// Функции для управления главным циклом приложения, регистрации
// колбеков для создания приложения и его завершения.
#include <app.h>
// Функции для создания элементов пользовательского интерфейса
// и управления ими. Здесь находятся все виджеты, такие как: окна, кнопки и т.д.
#include <Elementary.h>
// Функции для использования колбеков аппаратной кнопки Назад и для
// использования расширенных виджетов для круглого экрана
#include <efl_extension.h>
typedef struct _UIData {
Evas_Object *win;
Evas_Object *conform;
} UIData;
static void
_win_back_cb(void *data, Evas_Object *obj, void *event_info)
{
UIData *ui = data;
elm_win_lower(ui->win);
}
static void
_conformant_create(UIData *ui)
{
ui->conform = elm_conformant_add(ui->win);
// Говорим конформанту занимать все выделенное ему пространство
// по горизонтали и вертикали
evas_object_size_hint_weight_set(ui->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_show(ui->conform);
}
static void
_window_create(UIData *ui)
{
// Создание и настройка главного окна
ui->win = elm_win_util_standard_add(NULL, NULL);
// Создание конформанта – в данном случае главного контейнера в приложении,
// который также является интерфейсом между нашим приложением и
// системными элементами, такими как клавиатура.
_conformant_create(ui);
// Устанавливаем размер конформант-виджета такой же, как и у окна
elm_win_resize_object_add(ui->win, ui->conform);
// Регистрируем функцию, которая будет вызываться
// при нажатии аппаратной кнопки Назад
eext_object_event_callback_add(ui->win, EEXT_CALLBACK_BACK, _win_back_cb, ui);
// Отображаем окно всегда только после того, как отображен весь базовый
// пользовательский интерфейс.
evas_object_show(ui->win);
}
static bool
_app_create_cb(void *data)
{
UIData *ui = data;
_window_create(ui);
return true;
}
static void
_app_terminate_cb(void *data)
{
UIData *ui = data;
// Перед завершением работы приложения удаляем главный виджет (окно),
// после чего удаляются все виджеты-дети этого окна (все виджеты нашего приложения).
evas_object_del(ui->win);
}
int
main(int argc, char *argv[])
{
UIData ui = {0,};
ui_app_lifecycle_callback_s lifecycle_callbacks = {0,};
// Регистрируем созданные нами функции, чтобы передать их в главный цикл
// нашего приложения.
lifecycle_callbacks.create = _app_create_cb;
lifecycle_callbacks.terminate = _app_terminate_cb;
// Вызов следующей функции запускает выполнение главного цикла приложения
return ui_app_main(argc, argv, &lifecycle_callbacks, &ui);
}