Alignment issues on screen transition

Hi, im using a universal loading screen. This screen is initialised in the main function. I have a wifi connect task and also a handler of when the IP is aquired. When it is aquired i want to use this loading screen again. The problem is that when this switch happens the screen aligns to the right. This is then for all the remaining screens and the webserver i create also aligns the screen even more to the right, when i refresh my webpage that is running on the webserver.

{
    if (!ui_Setup_Network){
        ui_Setup_Network = lv_obj_create(NULL);
        lv_obj_clear_flag(ui_Setup_Network, LV_OBJ_FLAG_SCROLLABLE); 
        lv_obj_set_size(ui_Setup_Network, LV_HOR_RES, LV_VER_RES);

        ui_Setup_Network_Load = lv_spinner_create(ui_Setup_Network, 1000, 90);
        lv_obj_set_width(ui_Setup_Network_Load, 80);
        lv_obj_set_height(ui_Setup_Network_Load, 80);
        lv_obj_align(ui_Setup_Network_Load, LV_ALIGN_CENTER, 0, 17);
        lv_obj_clear_flag(ui_Setup_Network_Load, LV_OBJ_FLAG_CLICKABLE);

        ui_Setup_Network_search = lv_label_create(ui_Setup_Network);
        lv_obj_set_width(ui_Setup_Network_search, LV_SIZE_CONTENT);   
        lv_obj_set_height(ui_Setup_Network_search, LV_SIZE_CONTENT);    
        lv_obj_align(ui_Setup_Network_search, LV_ALIGN_CENTER, 0, -70);
        lv_obj_set_style_text_font(ui_Setup_Network_search, &lv_font_montserrat_26, LV_PART_MAIN | LV_STATE_DEFAULT);
    } 
}

void ui_set_loading_screen_text(const char* text){
    if (ui_Setup_Network_search) {
        lv_obj_del(ui_Setup_Network);
        ui_Setup_Network = NULL; 
    }

    ui_Network_Search_screen_init();
    lv_label_set_text(ui_Setup_Network_search, text);
}

void ui_show_loading_screen(const char*text) {
    ui_set_loading_screen_text(text);
    ui_transition_to_new_screen(ui_Setup_Network);
}
type or paste code here

This is the switch

if (event_base == IP_EVENT) {
        switch (event_id) {
            case IP_EVENT_STA_GOT_IP:
                ESP_LOGW(TAG, "IP acquired");
                ui_show_loading_screen("http://192.168.4.1/index.html");
                xTaskCreate(configuration_setup_task, "lv_config_task", 4096, NULL, 5, NULL);
                break;
type or paste code here

Could you send a screenshot about the issue?

From the screen of my device or some code?

The screen of the device to see how the misalignment looks like. A video could be even better. :slight_smile:


The first is the normal alignment (note: this is also correct on the first time the loading screen is called), then after the switch u see the label and the spinner are aligned to the left. The 2nd picture is when i also refresh the webpage that runs in the task that is called after the loadingscreen call. So on switch it aligns like in picture 2 but not that far. then after webpage refresh it aligns like in picture 2. So in both instances this happens. Also i have tried changing the text on the page on picture 1. after i load in a new label it’s all good, but after i change the label text over and over it aligns to the left as well. So i think the issues lies within the change of label text and maybe the the use of the loading screen.

I see, but I don’t have any immediate ideas about what the problem could be.

Can you share some minimal (UI only) code to reproduce?

I’ll share the overlay u see on screenshot nr1. The loading screen code is at the top.

void ui_overlay_init(uint8_t * ssid){

    ui_Overlay = lv_obj_create(ui_Network_Selection); 
    lv_obj_set_size(ui_Overlay, LV_HOR_RES, LV_VER_RES);
    lv_obj_align(ui_Overlay, LV_ALIGN_CENTER, 0, 0);
    
    lv_obj_clear_flag(ui_Overlay, LV_OBJ_FLAG_SCROLLABLE); 

    ui_overlay_update_position();

    ui_overlay_content((const char *) ssid);
}

and this is the content inside the overlay

void ui_overlay_content(const char * ssid) {
   ui_Network_Selection_ssid_label = lv_label_create(ui_Overlay);
    lv_obj_set_width(ui_Network_Selection_ssid_label, LV_SIZE_CONTENT);   
    lv_obj_set_height(ui_Network_Selection_ssid_label, LV_SIZE_CONTENT);    
    lv_obj_align(ui_Network_Selection_ssid_label, LV_ALIGN_TOP_MID, 0, 75);
    lv_label_set_text(ui_Network_Selection_ssid_label, ssid);
    lv_obj_set_style_text_opa(ui_Network_Selection_ssid_label, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Network_Selection_ssid_label, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    ui_Network_Selection_Connect = lv_btn_create(ui_Overlay);
    lv_obj_set_width(ui_Network_Selection_Connect, 140);
    lv_obj_set_height(ui_Network_Selection_Connect, 39);
    lv_obj_align(ui_Network_Selection_Connect, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_flag(ui_Network_Selection_Connect, LV_OBJ_FLAG_SCROLL_ON_FOCUS);     
    lv_obj_clear_flag(ui_Network_Selection_Connect, LV_OBJ_FLAG_SCROLLABLE);      
    lv_obj_set_style_text_color(ui_Network_Selection_Connect, lv_color_hex(0xFFF9F9), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Network_Selection_Connect, 255, LV_PART_MAIN | LV_STATE_DEFAULT);

    ui_Network_Selection_ConnectLabel = lv_label_create(ui_Network_Selection_Connect);
    lv_obj_set_width(ui_Network_Selection_ConnectLabel, LV_SIZE_CONTENT);   
    lv_obj_set_height(ui_Network_Selection_ConnectLabel, LV_SIZE_CONTENT);    
    lv_obj_align(ui_Network_Selection_ConnectLabel, LV_ALIGN_CENTER, 0, 0);
    lv_label_set_text(ui_Network_Selection_ConnectLabel, "Connect");
    lv_obj_set_style_text_color(ui_Network_Selection_ConnectLabel, lv_color_hex(0xFCFCFC), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Network_Selection_ConnectLabel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Network_Selection_ConnectLabel, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    ui_Network_Selection_PasswordInput = lv_textarea_create(ui_Overlay);
    lv_obj_set_width(ui_Network_Selection_PasswordInput, 150);
    lv_obj_set_height(ui_Network_Selection_PasswordInput, 40);
    lv_obj_align(ui_Network_Selection_PasswordInput, LV_ALIGN_CENTER, 0, -50);
    lv_textarea_set_placeholder_text(ui_Network_Selection_PasswordInput, "password");
    lv_textarea_set_password_mode(ui_Network_Selection_PasswordInput, true);


    lv_obj_set_style_text_color(ui_Network_Selection_PasswordInput, lv_color_hex(0x646363),
                                LV_PART_TEXTAREA_PLACEHOLDER | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Network_Selection_PasswordInput, 255, LV_PART_TEXTAREA_PLACEHOLDER | LV_STATE_DEFAULT);

    ui_Network_Selection_Keyboard = lv_keyboard_create(ui_Overlay);
    lv_obj_set_width(ui_Network_Selection_Keyboard, LV_HOR_RES);
    lv_obj_set_height(ui_Network_Selection_Keyboard, 170);
    lv_obj_set_align(ui_Network_Selection_Keyboard, LV_ALIGN_BOTTOM_MID);
    lv_obj_add_flag(ui_Network_Selection_Keyboard, LV_OBJ_FLAG_HIDDEN);

    ui_Network_Selection_Back = lv_btn_create(ui_Overlay);
    lv_obj_set_width(ui_Network_Selection_Back, 100);   
    lv_obj_set_height(ui_Network_Selection_Back, 39);    
    lv_obj_set_align(ui_Network_Selection_Back, LV_ALIGN_TOP_LEFT);
    lv_obj_add_flag(ui_Network_Selection_Back, LV_OBJ_FLAG_SCROLL_ON_FOCUS);     
    lv_obj_clear_flag(ui_Network_Selection_Back, LV_OBJ_FLAG_SCROLLABLE); 
    lv_obj_set_style_text_color(ui_Network_Selection_Back, lv_color_hex(0xFFF9F9), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Network_Selection_Back, 255, LV_PART_MAIN | LV_STATE_DEFAULT);

    ui_Network_Selection_BackLabel = lv_label_create(ui_Network_Selection_Back);
    lv_obj_set_width(ui_Network_Selection_BackLabel, LV_SIZE_CONTENT);   
    lv_obj_set_height(ui_Network_Selection_BackLabel, LV_SIZE_CONTENT);    
    lv_obj_set_align(ui_Network_Selection_BackLabel, LV_ALIGN_CENTER);
    lv_label_set_text(ui_Network_Selection_BackLabel, "Back");
    lv_obj_set_style_text_color(ui_Network_Selection_BackLabel, lv_color_hex(0xFCFCFC), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(ui_Network_Selection_BackLabel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(ui_Network_Selection_BackLabel, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);

    lv_keyboard_set_textarea(ui_Network_Selection_Keyboard, ui_Network_Selection_PasswordInput);

    uint8_t * password = lv_textarea_get_text(ui_Network_Selection_PasswordInput);

    //event binders
    lv_obj_add_event_cb(ui_Network_Selection_Back, ui_event_back, LV_EVENT_CLICKED, NULL);
    lv_obj_add_event_cb(ui_Network_Selection_PasswordInput, ui_event_password_focus, LV_EVENT_FOCUSED, NULL);
    lv_obj_add_event_cb(ui_Network_Selection_PasswordInput, ui_event_password_focus, LV_EVENT_DEFOCUSED, NULL);
    lv_obj_add_event_cb(ui_Network_Selection_Connect, ui_event_wifi_connect, LV_EVENT_CLICKED, (void *)password);
}

this is the code for screenshot number 1, take note that this overlay is shown on top of another screen. This shoudn’t create this issue though.

This is the main function where the loading screen is called on the start of program.

void app_main(void)
{
    Touch_IO_RST();
    lvgl_hardWare_init();    
    ESP_LOGW(TAG, "init lvgl hd ok");

    xTaskCreate(lv_tick_task, "lv_tick_task", 1024*10, NULL, 1, NULL);

    ui_show_loading_screen("Searching For Network");
    
    xTaskCreate(wifi_init_task, "lv_wifi_task", 4096, NULL, 5, NULL);
}

I can’t see any obvious issues here. Have you used SquareLine to create the UI?

Yes, but i have significantly adjusted the code.

Have you experimented with different sync values in the screen driver? Sometimes the panel can be at an unstable sync point and then resync at a different point later.

No, i have not. I’ll take a look.

Still haven’t fixed the issues, yesterday i was working on something else, when it happend again while the code i shared with u guys wasn’t even running. That makes me think it isn’t related to the lvgl code. Also i haven’t tested the screen sync changes because they look good to me. Could be an underlying issues. It always happens when i start a Task with FreeRtos that start my webserver and filesystem. And it also happens when i save the configuration now so this also serializes the json to my struct (object) and then loads the ui based on that data ill share the functions were i think it happens.

It happens here, serving the web page. So on load of the webpage it happens.

esp_err_t send_web_page(httpd_req_t *req, const char *filepath, const char *content_type) {
    FILE *file = fopen(filepath, "r");
    if (!file) {
        ESP_LOGE(TAG, "File %s not found", filepath);
        return httpd_resp_send_404(req);
    }

    httpd_resp_set_type(req, content_type);

    char buffer[256];
    size_t read_bytes;

    while ((read_bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) {
        esp_err_t res = httpd_resp_send_chunk(req, buffer, read_bytes);
        if (res != ESP_OK) {
            fclose(file);
            ESP_LOGE(TAG, "Error sending chunk!");
            return res;
        }
    }

    httpd_resp_send_chunk(req, NULL, 0);
    fclose(file);

    return ESP_OK;
}

Also here, creating the object and processing the data. The process data function is just where i assign all the values of the json to the object and also allocate memory for them.

esp_err_t data_handler(httpd_req_t *req) {
    size_t content_len = req->content_len;
    ESP_LOGI(TAG, "Content length: %d", content_len);

    char *content = (char*)malloc(content_len + 1);
    if (content == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for request content");
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }

    size_t received = 0;
    int ret;

    while (received < content_len){
        ret = httpd_req_recv(req, content + received, content_len - received);
        if (ret <= 0) { 
            if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
                httpd_resp_send_408(req);
            }
            free(content);
            return ESP_FAIL;
        }
        received += ret;
    }

    content[content_len] = '\0';  // Null-terminate the received string
    ESP_LOGI(TAG, "Received: %s", content);

    process_data(content, req);

    // Send the data to the queue
    if (xQueueSend(config_queue, &response_data, portMAX_DELAY) != pdPASS) {
        ESP_LOGE(TAG, "Failed to send POST data to the queue");
    } else {
        ESP_LOGI(TAG, "POST data successfully sent to the queue");
    }

    const char resp[] = "Data is received and processed";
    httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}

Note: I do think it could be because of memory handeling, not enough freeing of memory maybe? I know this isn’t lvgl but it does relate to the issue.

I have found the issues. It was were indeed the sync values. Playing with the values in the rgb_panel_config, like vsync_back_porch etc. fixed the issue.

1 Like