How to avoid back menu button auto selection and how to handle list buttons selection

Description

What MCU/Processor/Board and compiler are you using?

Simulator

What LVGL version are you using?

8.3

What do you want to achieve?

I do want a Menu where the pages are lists and each button in the list can send me to a new page. The user will navigate through the Menu using keys, so in the simulator, I’m trying to navigate using my keyboard (only key left, right, up, and down).

What have you tried so far?

I’m pretty new in the LVGL world. Reading the documentation I found that by combining the Menu with the List I could achieve exactly what I wanted.


So I started to implement it, but I’m confused if I’m handling the selection of the buttons correctly. My feeling is that it could be more straightforward and maybe out of the box (mainly talking about lists).


Thus I would like the help of you to know if I’m handling the selection of the buttons in a list by LV_EVENT_KEY correctly. I would love to identify mistakes as early as possible.


Also, I’m facing kind of a “bug”. Whenever I go into a sub-page the back button is selected and I can’t navigate through the list buttons, so I’m always stuck and the only alternative is to press enter to go back (by the way, I’ll not have an enter key, it’ll be only up, down, left, and right).


How can I make the back button unselected when I enter a new page and how to navigate from it to the list buttons and vice-versa?


Honestly, I started to think about implementing this with only a list, labels(for titles), and buttons (back buttons) or a lightweight table list, labels, and buttons. I don’t know, this Menu seems to be making things worse, or I don’t know how to use it correctly (more probable).

Code to reproduce

This is the code that I have written so far. Of course, the code is not finished yet, for instance, the left key handling is not implemented, this is because I faced a bug related to the back button and I can’t even test some left implementation. However, the code has a good sense of what I’m trying to achieve.

static lv_obj_t *current_item = NULL;

static void page_changed_cb(lv_event_t * e) {
    lv_obj_t *menu = lv_event_get_user_data(e);
    lv_obj_t *page = lv_menu_get_cur_main_page(menu);
    lv_obj_t *container = lv_obj_get_child(page, 0);
    lv_obj_t *list = lv_obj_get_child(container, 0);
    uint32_t items_cnt = lv_obj_get_child_cnt(list);

    if (!items_cnt) return;

    current_item = lv_obj_get_child(list, 0);
    lv_event_send(current_item, LV_EVENT_FOCUSED, NULL);
}

void keyboard_event_cb(lv_event_t * e) {
    if (current_item == NULL) return;
    uint32_t current_item_index = lv_obj_get_index(current_item);
    lv_obj_t *parent = lv_obj_get_parent(current_item);
    uint32_t items_cnt = lv_obj_get_child_cnt(parent);
    int32_t code = *((int32_t *)lv_event_get_param(e));
    switch (code) {
        case LV_KEY_UP:
            LV_LOG_USER("up");
            if (!current_item_index) return;
            lv_event_send(current_item, LV_EVENT_DEFOCUSED, NULL);
            current_item = lv_obj_get_child(parent, current_item_index - 1);
            lv_event_send(current_item, LV_EVENT_FOCUSED, NULL);
            break;
        case LV_KEY_DOWN:
            LV_LOG_USER("down");
            if (current_item_index + 1 >= items_cnt) return;
            lv_event_send(current_item, LV_EVENT_DEFOCUSED, NULL);
            current_item = lv_obj_get_child(parent, current_item_index + 1);
            lv_event_send(current_item, LV_EVENT_FOCUSED, NULL);
            break;
        case LV_KEY_RIGHT:
            LV_LOG_USER("right");
            lv_event_send(current_item, LV_EVENT_DEFOCUSED, NULL);
            lv_event_send(current_item, LV_EVENT_CLICKED, NULL);
            break;
        case LV_KEY_LEFT:
            LV_LOG_USER("left");
            break;
        default:
            LV_LOG_USER("not found");
    }
}

void ui(void) {
    // BEGIN: Menu setup
    lv_obj_t *menu = lv_menu_create(lv_scr_act());
    lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
    lv_obj_center(menu);

    lv_obj_t *back_btn = lv_menu_get_main_header_back_btn(menu);
    lv_obj_t *back_btn_label = lv_label_create(back_btn);
    lv_label_set_recolor(back_btn_label, true);
    lv_label_set_text(back_btn_label, "#ff0000 Back#");


    lv_obj_t *cont = NULL;
    lv_obj_t *list = NULL;
    lv_obj_t *button = NULL;

    // Begin: Page 1
    lv_obj_t *page_1 = lv_menu_page_create(menu, "Page 1");
    cont = lv_menu_cont_create(page_1);
    list = lv_list_create(cont);
    lv_obj_set_size(list, MONITOR_HOR_RES * 0.9, MONITOR_VER_RES * 0.9);
    lv_obj_center(list);

    button = lv_list_add_btn(list, NULL, "Page 1 item 1");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    button = lv_list_add_btn(list, NULL, "Page 1 item 2");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    button = lv_list_add_btn(list, NULL, "Page 1 item 3");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    button = lv_list_add_btn(list, NULL, "Page 1 item 4");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    //


    // Begin: Page 2
    lv_obj_t *page_2 = lv_menu_page_create(menu, "Page 2");
    cont = lv_menu_cont_create(page_2);
    list = lv_list_create(cont);
    lv_obj_set_size(list, MONITOR_HOR_RES * 0.9, MONITOR_VER_RES * 0.9);
    lv_obj_center(list);

    button = lv_list_add_btn(list, NULL, "Page 2 item 1");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    button = lv_list_add_btn(list, NULL, "Page 2 item 2");
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    //


    // Begin: Main page
    lv_obj_t *main_page = lv_menu_page_create(menu, "Actions");

    cont = lv_menu_cont_create(main_page);
    list = lv_list_create(cont);
    lv_obj_set_size(list, MONITOR_HOR_RES * 0.9, MONITOR_VER_RES * 0.9);
    lv_obj_center(list);


    button = lv_list_add_btn(list, NULL, "Page 1");
    lv_menu_set_load_page_event(menu, button, page_1);
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    current_item = button;

    button = lv_list_add_btn(list, NULL, "Page 2");
    lv_menu_set_load_page_event(menu, button, page_2);
    lv_obj_add_event_cb(button, keyboard_event_cb, LV_EVENT_KEY, menu);
    //

    lv_menu_set_page(menu, main_page);
    lv_obj_add_event_cb(menu, page_changed_cb, LV_EVENT_VALUE_CHANGED, menu);
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.
1

For control any screen menu too you need use indev grouping.

I had configured the keyboard. In the image with the title “Actions” I can use the up/down arrows to navigate. The problem is that once I go into a subpage, I’m stuck in the back button. I can’t go to the options below.