List focus doesn't work


List focus doesn’t work, but it works with drop down

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


What do you experience?

I wrote the code from sniped 1 and with the 4 buttons on the PCB I can scroll through the drop down, select or cancel.
Then I changed the code to sniped 2 by removing the drop down and replacing it with a list and now I cannot scroll through the list with the buttons. I think the list is not focus now, wright? How to get it working? Thank you!

What do you expect?

Navigate through the list

Code to reproduce

Sniped 1:

lv_group_t * g = lv_group_create();
lv_indev_set_group(my_indev, g);
//Create a drop down list
lv_obj_t * ddlist = lv_dropdown_create(lv_scr_act(), NULL);

lv_obj_set_width(ddlist, 200);
//lv_ddlist_set_draw_arrow(ddlist, true);
lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, -4, 0);
//lv_obj_set_event_cb(ddlist, event_handler);

lv_group_add_obj(g, ddlist);

Sniped 2:

lv_group_t * g = lv_group_create();
lv_indev_set_group(my_indev, g);

lv_obj_t * list1 = lv_list_create(lv_scr_act(), NULL);
lv_obj_set_size(list1, LV_HOR_RES_MAX-8, LV_VER_RES_MAX);
lv_obj_align(list1, NULL, LV_ALIGN_CENTER, -4, 0);

//Add buttons to the list
lv_obj_t * list_btn;

list_btn = lv_list_add_btn(list1, LV_SYMBOL_FILE, "New");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_DIRECTORY, "Open");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_CLOSE, "Delete");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_EDIT, "Edit");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_SAVE, "Save");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_BELL, "Notify");
//lv_obj_set_event_cb(list_btn, event_handler);

list_btn = lv_list_add_btn(list1, LV_SYMBOL_BATTERY_FULL, "Battery");
//lv_obj_set_event_cb(list_btn, event_handler);

lv_group_add_obj(g, list1);

Screenshot and/or video


To which LV_KEY_... have you mapped you buttons?
Can you share your indev_read function?

Here are my functions for reading the buttons. I have to because the second checks when the buttons are released:

uint8_t my_btn_read(void)
        return LV_KEY_UP;
    else if(bsp_button_is_pressed(1))
        return LV_KEY_DOWN;
    else if(bsp_button_is_pressed(2))
        return LV_KEY_ESC;
    else if(bsp_button_is_pressed(3))
        return LV_KEY_ENTER;
        return 0;

bool buttons_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
    static uint8_t last_btn = 0;         /* Store the last pressed button */
    uint8_t btn_pr = my_btn_read();      /* Get the ID (0,1,2...) of the pressed button */
    if(btn_pr > 0)                      /* Is there a button press? */
        last_btn = btn_pr;              /* Save the ID of the pressed button */
        data->state = LV_INDEV_STATE_PR;/* Set the pressed state */
    else                                /* Set the released state */
        data->state = LV_INDEV_STATE_REL;

    data->key = last_btn;               /* Set the last button */

//    data->key = last_key();            /*Get the last pressed or released key*/

//    if(key_pressed()) data->state = LV_INDEV_STATE_PR;
//    else data->state = LV_INDEV_STATE_REL;
    return false;

All looks good and it works for me in the simulator.
I added a keyboard indev like this:

  keyboard_init();          /*From lv_drivers repo*/
  lv_indev_drv_init(&indev_drv); /*Basic initialization*/
  indev_drv.type = LV_INDEV_TYPE_KEYPAD;
  indev_drv.read_cb = keyboard_read;
  my_indev = lv_indev_drv_register(&indev_drv);

And it looks like this:

Next time I will post all my code in the first post. Here is my init section for all lvgl related parts:

// LV init
    static lv_disp_buf_t disp_buf;              /*A static or global variable to store the buffers*/
    static lv_color_t buf_1[(LV_VER_RES_MAX) * (2 + (LV_HOR_RES_MAX / 8)) + 2]; /*Static or global buffer(s). The second buffer is optional*/
    lv_disp_buf_init(&disp_buf, buf_1, NULL, LV_HOR_RES_MAX*LV_VER_RES_MAX);/*Initialize `disp_buf` with the buffer(s) */
    lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
    disp_drv.buffer = &disp_buf;            /*Set an initialized buffer*/
    disp_drv.flush_cb = sharp_mip_flush;   /*Set a flush callback to draw to the display*/
    disp_drv.rounder_cb = sharp_mip_rounder;
    disp_drv.set_px_cb = sharp_mip_set_px;
    lv_disp_t * disp;
    disp = lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/
    // LV keypad init
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);      /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_KEYPAD;                 /*See below.*/
    indev_drv.read_cb = buttons_read;              /*See below.*/
    lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

Okay, actually my code was always working. The problem was that I couldn’t see which button is focused, like in the animation you posted. If I press the down button it scrolls after 5 clicks - when the list has to scroll.

I use mono display and the default theme is set to mono. Perhaps that’s why I cannot see the focused button. Is there an option for changing this - i.e. when a button is focused it turns black? The list fills my whole display and I want to use it as a menu - there will be sub-menus as well.

Drop down with visible selected field:

List without visible selected field, I want to achieve the same effect as the picture above):

Thank you!

Oh, I see.

You add custom appearance for focused state like this:

    static lv_style_t style_btn;
    lv_style_set_bg_color(&style_btn, LV_STATE_FOCUSED, LV_COLOR_BLACK);
    lv_style_set_text_color(&style_btn, LV_STATE_FOCUSED, LV_COLOR_WHITE);
    lv_style_set_image_recolor(&style_btn, LV_STATE_FOCUSED, LV_COLOR_WHITE);
    lv_style_set_bg_opa(&style_btn, LV_STATE_FOCUSED, LV_OPA_COVER);

    list_btn = lv_list_add_btn(list1, LV_SYMBOL_FILE, "New");
    lv_obj_add_style(list_btn, LV_BTN_PART_MAIN, &style_btn);

Thank you!