У цьому уроку ми розглянемо спливаючі вікна, ціль і спосіб їх використання. У кінці уроку, в якості практики, покажемо, як додати спливаюче вікно для підтвердження запиту на закриття додатку користувачем.
Часто в додатках виникає необхідність відобразити важливу інформацію поверх всього інтерфейсу користувача або запитувати підтвердження і/або відміну дії. Для цього можна використовувати вікно (Popup).
Для створення віджета використовується наступна функція:
Evas_Object *elm_popup_add(Evas_Object *parent);
Як і з іншими віджетами, щоб відобразити вікно, необхідно викликати функцію evas_object_show().
Цей віджет підтримує зникнення з затримкою, таким чином можна відобразити інформацію і через декілька секунд автоматично згорнути popup. Для встановлення такої затримки і її тривалості використовується наступна функція:
void elm_popup_timeout_set(Evas_Object *obj, double timeout);
Тут першим параметром передається вказівник на об’єкт спливаючого вікна, а другим – кількість секунд, через яку необхідно звернути вказаний віджет.
У деяких стилях спливаючого вікна може бути реалізовано звертання вікна з анімацією. Для того аби звернути віджет з таким ефектом, потрібно використовувати наступну функцію:
void elm_popup_dismiss(Evas_Object *obj);
Зверніть увагу, що після виклику цієї функції, спливаюче вікно стане невидимим, але не буде видалено. Тому, якщо ви хочете його видалити, ви повинні дочекатись кінця анімації, а потім в обробнику цієї події видалити віджет за допомогою функції evas_object_del(). Події для спливаючих вікон ми розглянемо далі в цьому уроку. Якщо ви викличете функцію evas_object_hide(), то вікно миттєво зникне, без будь-якого ефекту.
Оскільки тут використовується круглий інтерфейс, необхідно це явно вказувати для віджету, наступним викликом:
elm_object_style_set(popup, "circle");
Стилі для спливаючих вікон реалізовані трохи інакше ніж в інших віджетах, оскільки popup деякою мірою є контейнером. Загалом, процес встановлення стилю відбувається наступним чином: створюється об’єкт макету, потім йому встановлюється один з вибраних стилів, передбачених для спливаючих вікон. І потім, в залежності від вибраного стилю, спливаюче вікно заповнюється контентом.
Розглянемо стилі макетів для спливаючих вікон.
Стиль "layout/popup/content/circle":
Ім’я стилю макету – це комбінація з назви класу, групи і стилю. У кожного представленого стилю клас – це "layout", далі слідує група "popup" і стиль - "content/circle". Встановити даний стиль для макету можна з допомогою наступної функції:
elm_layout_theme_set(layout, "layout", "popup", "content/circle");
Ми вже робили дещо подібне, коли розглядали макети в 12-му уроці.
Даний стиль представляє собою дві області, в які можна встановити текст ("elm.text" – ім’я області для основного тексту, "elm.text.title" – ім’я області для тексту заголовку), а також одна область для встановлення кнопки, яка буде знаходитись внизу екрану.
Якщо текст надто довгий, внутрішня реалізація спливаючого вікна додає скроллер. Тепер, якщо розмір тексту перевищує висоту віджету, текст почне прокручуватись.
Встановлення кнопок у спливаючому вікні відбувається не напряму в макет, як це було з текстом, а представленим нижче викликом, прямо в popup.
elm_object_part_content_set(popup, "button1", button);
У версії віджету для носимих пристроїв з круглим екраном, буває дві таких області для кнопок. Як ви могли здогадатись, їх назви: "button1" і "button2".
Стиль "layout/popup/content/circle/buttons1".
Це розширений за рахунок області анімації кнопки, стиль "layout/popup/content/circle". Структурно ці два стилі нічим не відрізняються.
Стиль "layout/popup/content/circle/buttons2".
Як і макет "content/circle" і "content/circle/buttons1", цей стиль має текстову зону і заголовок. Але відрізняється тим, що в ньому є дві кнопки: зліва (button1) і справа (button2), замість однієї знизу. Ми вже розглядали в уроці 14 стилі кнопок ("popup/circle/left" і "popup/circle/right"), передбачених спеціально для цих областей.
Далі ми розглянемо, як додати спливаюче вікно з таким стилем до демо-додатку для підтвердження завершення його роботи.
Віджет підтримує наступні смарт події:
"timeout" – подія спрацьовує після закінчення часу, заданого викликом функції elm_popup_timeout_set(), коли спливаюче вікно автоматично зникає.
"block,clicked". Деякі стилі спливаючих вікон мають область, яка для уникнення дій з головним інтерфейсом користувача, перекриває його. Коли користувач натискає на цю область, дана подія спрацьовує.
У спливаючому вікні зі стилем "circle/toast" така область розміщена поверх всього інтерфейсу користувача і поверх самого віджету. Таким чином, якщо користувач натисне в будь-якому місці спливаючого вікна, спрацює дана подія. Зазвичай при такій дії, варто закривати popup.
"show,finished" – подія відбувається після завершення анімації відображення спливаючого вікна.
"dismissed" – подібно до попередньої, дана подія спрацьовує тільки після анімації зникання спливаючого вікна, як результат виклику функції elm_popup_dismiss(), яку ми розглянули раніше.
"language,changed" – оскільки спливаюче вікно наслідується від макету, цей сигнал також підтримується. Ви можете обробляти зміну мови в системі, якщо зареєструєте колбек на даний сигнал.
Перейдемо до практики і завершимо цей демо-додаток. Ми будемо створювати спливаюче вікно з двома кнопками: відміна і підтвердження. Крім того, буде відображено питання про закриття додатку. У разі підтвердження – додаток буде закриватись, інакше – видаляти спливаюче вікно по натисканню на кнопку Скасувати або апаратної кнопки Назад.
У структуру з віджетами додайте вказівник на спливаюче вікно.
Evas_Object *popup;
Тепер вийшла ось така структура:
typedef struct _UIData {
Evas_Object *win;
Evas_Object *conform;
Evas_Object *layout;
Evas_Object *button;
Evas_Object *label;
Evas_Object *popup;
int click_count;
} UIData;
Підготуйте нову функцію, з допомогою якої створіть спливаючі вікна.
static void
_exit_popup_create(UIData *ui)
{
}
Створіть об’єкт спливаючого вікна і встановіть йому круглий стиль.
ui->popup = elm_popup_add(ui->layout);
elm_object_style_set(ui->popup, "circle");
Тепер створіть макет для контенту і встановіть йому стиль "content/circle/buttons2" і потім встановіть його як вміст для popup.
Evas_Object *popup_layout = elm_layout_add(ui->popup);
elm_layout_theme_set(popup_layout, "layout", "popup", "content/circle/buttons2");
elm_object_content_set(ui->popup, popup_layout);
Після створення макету, можна встановити основний текст і заголовок.
elm_object_part_text_set(popup_layout, "elm.text", "Закрити додаток?");
elm_object_part_text_set(popup_layout, "elm.text.title", "Підтвердження");
Тепер потрібно розібратись з кнопками для спливаючого вікна.
Будемо використовувати дві кнопки зі стилями "popup/circle/left" і "popup/circle/right". З допомогою віджета-зображення, додайте у ці кнопки дві іконки.
Можете скористатись наданими ресурсами, скачавши представлені нижче зображення і помістивши їх в папку res/ вашого проекту.
Ми зараз не будемо детально розглядати віджет для відображення зображень, можете просто скопіювати у ваш код дві наступні функції для створення віджету з вказаним зображенням.
static void
_file_abs_resource_path_get(char *res_file_path, char *abs_path, int buf_size)
{
char *res_dir_path = app_get_resource_path();
if (res_dir_path)
{
snprintf(abs_path, buf_size, "%s%s", res_dir_path, res_file_path);
free(res_dir_path);
}
}
static Evas_Object *
_image_create(Evas_Object *parent, char *image_name)
{
Evas_Object *icon = elm_image_add(parent);
char image_path[PATH_MAX] = {0,};
_file_abs_resource_path_get(image_name, image_path, PATH_MAX);
elm_image_file_set(icon, image_path, NULL);
evas_object_show(icon);
return icon;
}
Виклик останньої функції створить і поверне об’єкт віджет-зображення. У функцію необхідно передати батьківський віджет і назву зображення, що знаходиться в папці res/ вашого проекту.
Створіть функцію, яка буде використовуватись для створення кнопок спливаючого вікна, куди буде передаватись батьківський віджет, стиль для кнопки і ім’я кнопки, які необхідно використати в кнопці.
static Evas_Object *
_popup_button_create(Evas_Object *parent, char *style, char *icon_name)
{
Evas_Object *button = elm_button_add(parent);
elm_object_style_set(button, style);
Evas_Object *btn_icon = _image_create(button, icon_name);
elm_object_content_set(button, btn_icon);
evas_object_show(button);
return button;
}
Ми детально розглянули кнопку і її створення в 14-му уроці.
Допоміжні функції були реалізовані, тепер скористайтесь ними для продовження створення спливаючого вікна. Створіть ліву кнопку для відміни виходу з додатку і помістіть її в область "button1" спливаючого вікна. Після цього, зареєструйте обробник натискання цієї кнопки.
static void
_exit_popup_create(UIData *ui)
{
...
Evas_Object *left_button = _popup_button_create(popup_layout, "popup/circle/left", "cancel.png");
elm_object_part_content_set(ui->popup, "button1", left_button);
evas_object_smart_callback_add(left_button, "clicked", _cancel_exit_cb, ui);
...
}
Створіть праву кнопку для підтвердження виходу з додатку та помістіть її в область "button2" спливаючого вікна. Потім одразу зареєструйте обробник натискання цієї кнопки.
static void
_exit_popup_create(UIData *ui)
{
...
Evas_Object *right_button = _popup_button_create(popup_layout, "popup/circle/right", "apply.png");
elm_object_part_content_set(ui->popup, "button2", right_button);
evas_object_smart_callback_add(right_button, "clicked", _apply_exit_cb, ui);
...
}
Реалізуйте невелику функцію для видалення спливаючого вікна.
static void
_remove_popup(UIData *ui)
{
evas_object_del(ui->popup);
ui->popup = NULL;
}
Після видалення об’єкту, встановіть вказівнику значення NULL, оскільки функціонал методу evas_object_del() не дозволяє зробити це автоматично, а вам далі потрібно стежити за тим, чи створено спливаюче вікно, якраз по стану вказівника на віджет.
Тепер реалізуйте функціонал обробників для створених кнопок.
static void
_cancel_exit_cb(void *data, Evas_Object *obj, void *info)
{
UIData *ui = data;
_remove_popup(ui);
}
static void
_apply_exit_cb(void *data, Evas_Object *obj, void *info)
{
ui_app_exit();
}
Тут в обробнику відміни виходу з додатку була використана функція видалення і скидання вказівника спливаючого вікна. В обробнику підтвердження виходу, викличте функцію для завершення роботи додатку.
Останнім кроком, потрібно відобразити спливаюче вікно вже знайомою функцією:
static void
_exit_popup_create(UIData *ui)
{
...
evas_object_show(ui->popup);
}
Теперь передайте функцию-обработчик нажатия аппаратной кнопки назад. Далі передайте функцію-обробник натискання апаратної кнопки Назад. Якщо popup ще не був створений, вам потрібно його створити і відобразити. В іншому випадку, потрібно видалити віджет. Обробник має виглядати наступним чином:
static void
_win_back_cb(void *data, Evas_Object *obj, void *event_info)
{
UIData *ui = data;
if (!ui->popup)
{
_exit_popup_create(ui);
}
else
{
_remove_popup(ui);
}
}
Запустіть додаток і подивіться як він працює.
На цьому створення спливаючого вікна у вашому демо-додатку pзавершено.
Повний початковий код цього уроку ви можете знайти тут WearLesson017.