How to move the position of the ddlist after calling lv_ddlist_set_selected

Description

I have a fairly long ddlist (~600 items) and I am trying to set a default position based on the current setting. This works fine, but whenever I create the drop-down list it always starts at the top of the list rather than the selected option.

Code to reproduce

lv_obj_t *mylist = lv_ddlist_create(lv_scr_act(), NULL);
lv_ddlist_set_options(mylist, list_of_options);
lv_ddlist_set_stay_open(mylist, true);
lv_ddlist_open(mylist, LV_ANIM_OFF);
lv_ddlist_set_selected(ddl_tz, index); // This sets the index correctly, but the ddlist is still at the top

Solution

I’ve figured it out as I was typing this all out. This is an order of operations issue, and perhaps an opportunity for improvement. If I move the lv_ddlist_set_selected() call to just before I open the list then it appears at the offset of my index. Arguably it should move the list to the position of the selected item after it’s opened as well. In either case I’ve figured out my own question and will leave this here in case anyone else runs into this!

lv_obj_t *mylist = lv_ddlist_create(lv_scr_act(), NULL);
lv_ddlist_set_options(mylist, list_of_options);
lv_ddlist_set_selected(ddl_tz, index); // Moving this up here fixes my issue
lv_ddlist_set_stay_open(mylist, true);
lv_ddlist_open(mylist, LV_ANIM_OFF);

Can you verify if it works to add lv_ddlist_pos_current_option(ddlist) to lv_ddlist_set_selected() if the list is alrady opened?

1 Like

This is the function implemented:

/**
 * Set the selected option
 * @param ddlist pointer to drop down list object
 * @param sel_opt id of the selected option (0 ... number of option - 1);
 */
void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt)
{
    lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
    if(ext->sel_opt_id == sel_opt) return;

    ext->sel_opt_id     = sel_opt < ext->option_cnt ? sel_opt : ext->option_cnt - 1;
    ext->sel_opt_id_ori = ext->sel_opt_id;
    /*Move the list to show the current option*/
    if(ext->opened == 0) {
        lv_ddlist_pos_current_option(ddlist);
    } else {
        lv_obj_invalidate(ddlist);
    }
}

It looks like it already has that in there?

Try moving it out of the if statement and always calling it. ext->opened == 0 is only true if the list is closed.

1 Like

Thanks for pointing that out. My brain hadn’t switched on yet. I did move it outside of the if, and it does appear to function as expected.

@tarvik Could send a Pull request? Just to be sure a tested version will be added.