Description
How can I change the number of entries of a list or roller during runtime?
What do you want to achieve?
Basically building some type of music player. Via web interface I can upload or delete files on an SD card inside the player. Via display I want to select which title to play. Hence I need a list of all available files on the SD card to select from. This list can change at anytime. Songs can be added or removed.
As far as I can see there are 2 types of widgtes in LVGL I could use. Lists and Roller. List do have function to add text to it, but non for removal. Rollers don’t even have a function to add text.
How would you solve this?
Hi @deadeye ,
Below is an example of how to do what you require using a drop down list or a roller you will need to generate the char *song_list[]
array from your file list at runtime. Be sure to add a terminating NULL entry as I have done manually in the example to show the concept, and then call the appropriate `load’ function for a dropdown or roller and it will populate the list for you.
char *song_list[] = {
"Song 1",
"Song 2",
"Song 3",
"Song 4",
"Song 5",
"Song 6",
"Song 7",
"Song 8",
"Song 9",
"Song 10",
NULL
};
void load_dd( lv_obj_t *dd_list ) {
static char *dd_options = NULL;
char *ptr, **list_ptr;
uint16_t idx;
uint32_t buf_size = 0, entry_cnt = 0;
if( dd_options ) free( dd_options );
list_ptr = song_list;
while( *list_ptr != NULL ) {
buf_size += strlen( *list_ptr++ );
entry_cnt++;
}
buf_size += entry_cnt; // The entry_cnt variable is the locations required for the \n characters and the terminating NULL for the drop down list texts.
dd_options = malloc( buf_size );
ptr = dd_options;
for( idx = 0; idx < entry_cnt; idx++ ) {
ptr += snprintf( ptr, (buf_size - (ptr - dd_options)), "%s\n", song_list[idx]);
}
*(ptr-1) = 0; // This will strip the final newline character and terminate the string with a NULL
lv_dropdown_set_options_static( dd_list, dd_options );
}
void dd_load_example( void ) {
lv_obj_t *dd_list;
dd_list = lv_dropdown_create(lv_scr_act());
load_dd( dd_list );
lv_obj_align(dd_list, LV_ALIGN_TOP_MID, 0, 10);
}
void load_roller( lv_obj_t *roller ) {
char *roller_options;
char *ptr, **list_ptr;
uint16_t idx;
uint32_t buf_size = 0, entry_cnt = 0;
list_ptr = song_list;
while( *list_ptr != NULL ) {
buf_size += strlen( *list_ptr++ );
entry_cnt++;
}
buf_size += entry_cnt; // The entry_cnt variable is the locations required for the \n characters and the terminating NULL for the drop down list texts.
roller_options = malloc( buf_size );
ptr = roller_options;
for( idx = 0; idx < entry_cnt; idx++ ) {
ptr += snprintf( ptr, (buf_size - (ptr - roller_options)), "%s\n", song_list[idx]);
}
*(ptr-1) = 0; // This will strip the final newline character and terminate the string with a NULL
lv_roller_set_options(roller, roller_options, LV_ROLLER_MODE_NORMAL);
free( roller_options );
}
void roller_load_example( void ) {
lv_obj_t *roller;
roller = lv_roller_create(lv_scr_act());
load_roller( roller );
lv_obj_align(roller, LV_ALIGN_CENTER, 0, 0);
}
I hope that makes sense…
Kind Regards,
Pete
Hello Pete,
First I got the concept wrong and thought that I have to erase an existing Roller or List before I can use this code to create an updated Widget. But this is not the case. This code simply updates the existing Roller or List Widget with the elements from the array of possible selections.
Very nice. I would make the “song_list” as an parameter to call the updating function with but otherwise this is the solution to my problem. It would be nice if those functions are implemented in the LVGL library as a permanent solution. I mean, I can’t be the only one with type of problem. Just imagine scanning for Wifi Networks or devices in an smart home. In all this cases you will need to dynamically update some sort of List to select from.
So thank you for your support. Case closed 
1 Like