У цьому уроку ми розглянемо користувацький інтерфейс шаблону, який було створено в 7-му уроці, очистимо його від зайвого коду, щоб у подальшому ви могли використовувати цей шаблон для написання ваших демо-додатків.
Тепер, знаючи з чого складається користувацький інтерфейс, давайте розберемо стандартний шаблон, який ми створили в 7-му уроці. Почнемо з вікна (Win). Win – це кореневий елемент екрану. Він буде батьком для решти компонентів.
Вікно створюється з допомогою функції:
elm_win_util_standard_add(const char *name, const char *title);
Ця функція похідна від функції:
elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type);
Дана функція створює стандартне вікно з заданим ім’ям. Відмінність першої функції від другої полягає в тому, що вона створює вікно з уже доданим віджетом фону і присвоює вікну заголовок (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);
Також можна дати рекомендації з приводу розміру конформанта. Наступна функція прописує, що конформант буде займати весь виділений йому простір по горизонталі і вертикалі.
evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
Наступний рядок означає, що вікно обумовлює розміри конформанта, тобто розміри конформанта змінюються так, щоб відповідати розмірам вікна.
elm_win_resize_object_add(ad->win, ad->conform);
Конформант відображається наступним викликом:
evas_object_show(ui->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_del(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);
}