Best practices to use LittlevGL

I am using LittlevGL in my embedded project. I have managed to

  1. Port LittlevGL to my board (Nordic’s nRF52840)
  2. Create screens as per my requirements

Currently my code is like this.

screen1.c

void create_screen_with_btns(lv_event_cb_t event_cb)
{
\\ A simple code to create two buttons to the current screen
\\ When creating one of the buttons set event_cb as event handle
}

main.c

void event_handler(lv_obj_t * obj, lv_event_t event)
{
	if (event == LV_EVENT_CLICKED) {
                printf("Clicked: %s\n", lv_list_get_btn_text(obj));
                lv_obj_clean(lv_scr_act());
                //Call another function to do some work.
	}
}

int main()
{
    create_screen_with_btns(event_handler); // Call screen1.c to create buttons
    
    while(1)
    {
        lv_task_handler();
        delay(50);
    }
}

I am having difficulty scaling with the above design method.

For example I want to return something from an event handler or pass more parameters.

If I have many functionality in my code then I will be calling event handler which will be calling another function then that function will create another screen which will call another event handler. This cycle will go on.


Does anybody have any suggestion on how to work with LittlevGL ? How to structure my flow ?

Instead of returning a value, I usually call a set_something() function. E.g. on button click call set_max_rpm(get_max_rpm() + 1)

For me, it usually looks like calling an xyz_screen_create() function in an event. LittlevGL handles it well and it’s also clean IMO.

A related thing: usually I have the following project structure:

  • simulator_root
    • drivers
    • gui (submodule)
      • components
      • screens
      • lvgl (submodule)
      • lv_conf.h
    • other folders

And the same for hardware projects too. Only the drivers are different.
This way it easy to switch between the simulator and real hardware.

In the components folder, I create project-specific UI components with very simple API. E.g.

  • gui_slider_create(parent, event_cb, min, max) It can create a slider with a default size, styles, and add a label to indicate the current value.
  • gui_slider_set_value(slider, value)
  • gui_slider_get_value(slider)