Enable scroll for any text in a label, regardless of size

What LVGL version are you using?

V8.0

What do you want to achieve?

Scrolling of text regardless of size, but keeping the start and end locations the same.

What have you tried so far?

Just padding the text to overflow the box, but this doesn’t take into consideration the text width, so have to guess how many blank spaces to apply.

headerText = lv_label_create(lv_scr_act());
lv_obj_set_width(headerText, 300);
lv_obj_align(headerText, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_text_align(headerText, LV_TEXT_ALIGN_CENTER, 0);
lv_label_set_long_mode(headerText, LV_LABEL_LONG_SCROLL_CIRCULAR);

lv_label_set_text(headerText,"HOME                                    ");

It’s not possible with long modes but you can create a normal animation:


static void set_x(void * var, int32_t v)
{
    lv_obj_set_x(var, v);
}

...
 lv_obj_t * obj = lv_obj_create(lv_scr_act());
  lv_obj_center(obj);

  lv_obj_t * label = lv_label_create(obj);
  lv_label_set_text(label, "Home");
  lv_obj_add_flag(label, LV_OBJ_FLAG_FLOATING); /*To be ignored by scrollbars*/
  lv_obj_update_layout(obj);    /*To have the correct size for lv_obj_get_width*/

  lv_anim_t a;
  lv_anim_init(&a);
  lv_anim_set_var(&a, label);
  lv_anim_set_values(&a, lv_obj_get_width(obj) + 20, -lv_obj_get_width(label) - 20);
  lv_anim_set_time(&a, 3000);
  lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
  lv_anim_set_exec_cb(&a, set_x);
  lv_anim_start(&a);

t

Thank you @kisvegabor, hadn’t thought about just moving the label in x. I may have to think a little more on this, because the text length will change, so some text would be long enough to trigger the built in scroll and some not. So would have to calulcate if the scroll is triggered or not as to whether to run the animation.

It may be easier to just stick with padding the text to force it into scrolling.

Would LVGL be open to having a LV_LABEL_AWLAYS_SCROLL_CIRCULAR, or something of that nature to scroll any text regardless of length?

So I have done this, feels hacky, but it works. Is there somewhere we can add a feature request for a foreced scroll?

        // calculate size of text to be set
        lv_point_t size;
        lv_txt_get_size(&size, headerCharArray, lv_obj_get_style_text_font(headerText, LV_PART_MAIN), 
                                                lv_obj_get_style_text_letter_space(headerText, LV_PART_MAIN),
                                                lv_obj_get_style_text_line_space(headerText, LV_PART_MAIN),
                                                LV_COORD_MAX,
                                                headerText->flags);
        //get the actual size of header text                    
        lv_area_t txt_coords;
        lv_obj_get_content_coords(headerText, &txt_coords);

        //determine if we need padding
        int16_t padSize = lv_area_get_width(&txt_coords) - size.x;
        char textBuf[255] = "";
        LV_LOG_USER("Label size %d, textSize %d, padSize %d\n", lv_area_get_width(&txt_coords), size.x, padSize);
        if(padSize > -1){
            //if the text needs padding, grab the width of a blank space
            lv_txt_get_size(&size, " ", lv_obj_get_style_text_font(headerText, LV_PART_MAIN), 
                                                lv_obj_get_style_text_letter_space(headerText, LV_PART_MAIN),
                                                lv_obj_get_style_text_line_space(headerText, LV_PART_MAIN),
                                                LV_COORD_MAX,
                                                headerText->flags);
            //lets left pad the incoing text into a new buffer
            sprintf(textBuf,"%*s%s", (padSize / size.x) + 1, "", headerCharArray);
        } else {
            // no padding, copy text into buffer
            sprintf(textBuf,"%s", headerCharArray);
        }
        // set text, and set to scroll
        lv_label_set_text(headerText, textBuf);
        lv_label_set_long_mode(headerText, LV_LABEL_LONG_SCROLL_CIRCULAR);

Let’s understand the problem and goal first. Can you describe the exact use case? Why do you need a small text to be scrolled?

I didn’t know about this sprintf feature. Nice :slight_smile:

I guess I don’t NEED to have scrolling text, but I have implemented a screen header which has the time, some icons (SD Card, USB connected etc…) and a screen title.

When the device has an alarm, in this case it could be a high temperature alarm or something of that nature, I wish to flash the header background red and scroll the text which will describes the alarm details.

Sometimes this text, is smaller than the label, does not scroll and therfore does not have the same impact as a longer alarm text that scrolls.

As a feature, I just thought if it is easy to implement in LVGL it would be cleaner than the fancy use of sprintf.


I see. Thinking about it this feature seems a litle bit custom. I haven’t found similar features in other libraries/platforms (e.g. CSS/HTML).

For now, I suggest using your sprintf method.

I move this topic to the Feature request category so that others can comment if they also need this feature.