Description
I have read a number of posts and am still not clear on the right way to switch screens.
I am currently getting these messages:
[00:03:16.909,606] lvgl: (196.909, +196909) lv_obj_del: the active screen was deleted (in lv_obj_tree.c line #77)
[00:03:16.910,064] <wrn> lvgl: (196.909, +0) lv_obj_get_disp: No screen found (in lv_obj_tree.c line #287)
[00:03:16.910,217] <wrn> lvgl: (196.910, +1) lv_obj_get_disp: No screen found (in lv_obj_tree.c line #287)
[00:03:16.910,369] <wrn> lvgl: (196.910, +0) lv_obj_get_disp: No screen found (in lv_obj_tree.c line #287)
[00:03:16.910,522] <wrn> lvgl: (196.910, +0) lv_obj_get_disp: No screen found (in lv_obj_tree.c line #287)
Occasionally I get errors. I’m not sure if I should declare all the screens and swap them, or recreate them on the fly, or something else. I do see some beautiful screens and transitions with lvgl and wish there was a sample in the Zephyr repository.
What MCU/Processor/Board and compiler are you using?
Zephyr, Nordic branch, nRF52 and nRF53
What LVGL version are you using?
8.3
What do you want to achieve?
I want to have a standard way to switch between screens on a wearable display by swiping from one to the next.
What have you tried so far?
I’ve tried declaring the screens then removing them and re-creating them. I have deleted screens, but sometimes I don’t know the calling screen.
Code to reproduce
This code is based on the lvgl sample in Zephyr.
The code block(s) should be formatted like:
//screens
static lv_obj_t *scr_home;
static lv_obj_t *scr_left;
int create_screen_home();
int create_screen_left();
//callback
static void handle_screen_gesture(lv_dir_t event_code);
static void lv_btn_click_callback_left(lv_event_t *e)
{
LOG_DBG("Button press left");
ARG_UNUSED(e);
lv_obj_del(scr_left);
create_screen_home();
}
static void on_lvgl_screen_gesture_event_callback(lv_event_t *e)
{
LOG_DBG("Gesture event detected %d", e->code);
lv_dir_t dir;
lv_event_code_t event = lv_event_get_code(e);
if (event == LV_EVENT_GESTURE) {
dir = lv_indev_get_gesture_dir(lv_indev_get_act());
handle_screen_gesture(dir);
}
lv_indev_wait_release(lv_indev_get_act()); // Needed otherwise accidental button press will happen
}
static void handle_screen_gesture(lv_dir_t event_code)
{
switch (event_code) {
case LV_DIR_LEFT: {
LOG_DBG("LEFT gesture detected");
create_screen_left();
break;
}
case LV_DIR_RIGHT: {
LOG_DBG("RIGHT gesture detected");
//watchface_change();
break;
}
case LV_DIR_TOP: {
LOG_DBG("TOP gesture detected");
//create_screen_top();
break;
}
case LV_DIR_BOTTOM: {
LOG_DBG("BOTTOM gesture detected");
//create_screen_bottom();
break;
}
default:
LOG_ERR("Not a valid gesture code: %d", event_code);
}
}
int create_screen_home()
{
scr_home = lv_obj_create(NULL);
lv_scr_load_anim(scr_home, LV_SCR_LOAD_ANIM_NONE, 0, 0, true);
lv_obj_t *hello_world_label;
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_color(lv_scr_act(), lv_color_white(), LV_PART_MAIN);
hello_world_label = lv_label_create(lv_scr_act());
lv_label_set_text(hello_world_label, "Test Swipe!");
lv_obj_align(hello_world_label, LV_ALIGN_CENTER, 0, 0);
lv_obj_add_event_cb(lv_scr_act(), on_lvgl_screen_gesture_event_callback, LV_EVENT_GESTURE, NULL);
}
int create_screen_left()
{
scr_left = lv_obj_create(NULL);
// Used this function as it automatically deletes previous screen.
// Should work as you did also I think. But have not used lv_scr_load_xxx before
lv_scr_load_anim(scr_left, LV_SCR_LOAD_ANIM_NONE, 0, 0, true);
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_color(lv_scr_act(), lv_color_white(), LV_PART_MAIN);
lv_obj_t *label = lv_label_create(lv_scr_act());
if (IS_ENABLED(CONFIG_LV_Z_POINTER_KSCAN) || IS_ENABLED(CONFIG_LV_Z_POINTER_INPUT)) {
lv_obj_t *home_button;
home_button = lv_btn_create(lv_scr_act());
lv_obj_align(home_button, LV_ALIGN_CENTER, 0, 0);
lv_obj_add_event_cb(home_button, lv_btn_click_callback_left, LV_EVENT_CLICKED,
NULL);
label = lv_label_create(home_button);
} else {
label = lv_label_create(lv_scr_act());
}
lv_label_set_text(label, "LV_DIR_LEFT (1)");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_text_font(label, &lv_font_montserrat_16, LV_PART_MAIN);
lv_obj_add_event_cb(lv_scr_act(), on_lvgl_screen_gesture_event_callback, LV_EVENT_GESTURE, NULL);
return 0;
}