How to modify/start animation on text

Description

Based on Lvgl 6.0, customize animation

What MCU/Processor/Board and compiler are you using?

STM32L496xx

What do you want to achieve?

I would like to set an animation into a menu:
When a submenu is selected, start animation (if text too long)
Animation description:
Wait

a.act_time = -1000;

Move from left to right (faster than default speed from LV_LABEL_LONG_SROLL) then stop for a while

a.repeat_pause = 500;

Then go back directly to start (no move from right to left)

What have you tried so far?

First of all i tried to do it using LV_LABEL_LONG_SROLL, it works only on the first submenu when im entering into the menu, then “on select” i apply LV_LABEL_LONG_SROLL on the next element and set the old one to LV_LABEL_LONG_EXPAND (default). But nothing happened on the next element.
I don’t understand how to ask littlevgl that an animation is asked on a label.

lv_label_set_long_mode(mItemsLabel[mCurrentAdvancedProtState],LV_LABEL_LONG_EXPAND);
lv_label_set_long_mode(mItemsLabel[aState],LV_LABEL_LONG_SROLL);

this first command stops animation on the old submenu but the second one doesn’t trigg the animation (even with invalidate obj)

Then i would like to customize LV_LABEL_LONG_SROLL animation to fit my need but for now i got no idea about the best solution: possibility to customize an existing one ? or should i write a specific animation ?

PS: i’m a new LittlevGL user

Update:
I modified LV_LABEL_LONG_SROLL management and got this code:

static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x)
{
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
ext->offset.x = -x;
lv_obj_invalidate(label);
}

#pragma optimize=none
static void adisAnimationManagement(lv_obj_t * aObj)
{
lv_anim_t anim;
lv_coord_t wObjWidth;
lv_label_ext_t * ext = lv_obj_get_ext_attr(aObj);

wObjWidth = lv_obj_get_width(aObj);
lv_coord_t max_w         = lv_obj_get_width(aObj);
const lv_style_t * style = lv_obj_get_style(aObj);
const lv_font_t * font   = style->text.font;

ext->offset.x = 0;
ext->offset.y = 0;
ext->expand = 1;
ext->anim_speed = 25;
ext->long_mode = LV_LABEL_LONG_SROLL;

lv_point_t size;
lv_txt_get_size(&size, ext->text, font, style->text.letter_space, style->text.line_space, max_w, LV_TXT_FLAG_EXPAND);
size.x += 10; //add padding left

anim.var            = aObj;
anim.repeat         = 1;
anim.playback       = 0;
anim.start          = 0;
anim.ready_cb       = NULL;
anim.path_cb        = lv_anim_path_linear;
anim.repeat_pause   = 1000;
anim.act_time       = 0;

if((wObjWidth+10U) > ADIS_LCD_PIXEL_W)
{
anim.end     = (wObjWidth + 20U ) - ADIS_LCD_PIXEL_W; /* 10PL+5PR */
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
anim.time    = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
lv_anim_create(&anim);
}
else
{
    /*Delete the offset animation if not required*/
    lv_anim_del(aObj, (lv_anim_exec_xcb_t)lv_label_set_offset_x);
    ext->offset.x = 0;
}


lv_obj_invalidate(aObj);
/* delete anim from previous obj */
lv_anim_del(mItemsLabel[mCurrentAdvancedProtState], (lv_anim_exec_xcb_t)lv_label_set_offset_x);

}

seems to work as i want except one point:
when the first animation is done, i wait for a while then i start again.
What i would like to do is:
when the first animation is done, i wait for a while then i go back to start state and wait again for a while, then repeat.
Any idea please ?

Thanks in advance,
Best regards.

Update:
I’m using ready_cb to trig a timer, set position back to start and launch the same animation.
If someone got a better idea i’m looking forward to reading you

Suggestion:

  • it would be a good idea to add a new timer into animation struct “playback_time” which correspond to the animation back duration. (from 0, which set obj back to start position, to x). It would add a lot of flexibility on animation.
  • When set a new anim_speed on obj, update anim.time linked to this object. Which can add even more flexibility to change animation duration when we need.
  • Add a get_anim on a obj, to modify values from the anim struct (which allow doing the same action i’d like to do) in order to set a new anim.time

It’s because when you change to EXPAND long mode the size is expanded to text’s size and after there is nothing to SCROLL because the text fits into the label’s size. All you need to do is to reduce the label’s size with lv_obj_set_width(label, w) after changing to SCROLL.

There is no option for using simply an lv_anim_t. Using the ready_cb is a good idea.

I’ll think about it. For the record could you open topic for it in the Future request category?

All you need to do is to reduce the label’s size with lv_obj_set_width(label, w) after changing to SCROLL

Feeling bad … haha :sweat_smile:

Thanks for answer :slight_smile:

Don’t feel bad, it’s really not that obvious :slight_smile: