Add Text Crop to Table Widget

Description

Want to make a text inside a table cell cropped or better, circular scrolling.

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

ESP32

What LVGL version are you using?

8.1

What do you want to achieve?

Has written in the description I would like to make a long text inside a table cell or cropped, or better, circularly scrolling.

What have you tried so far?

Set flag LV_TABLE_CELL_CTRL_TEXT_CROP inside the LV_EVENT_DRAW_PART_BEGIN callback. Not Working.
Set the same flag inside the table definition function. Not Working.

Code to reproduce

The code block(s) should be formatted like:

/*You code here*/

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Hi!
Is there anyone with my same problem?

Thank you in advice!

In the meanwhile I have solved by creating a sort of bounce left and right of the text inside the cell.

The code is placed into the LV_EVENT_DRAW_PART_BEGIN callback function.

// Obtain the size of the text that should be drawn
lv_point_t size;
lv_txt_get_size(&size, lv_table_get_cell_value(table, row, col), dsc->label_dsc->font, dsc->label_dsc->letter_space, dsc->label_dsc->line_space,
            LV_COORD_MAX, dsc->label_dsc->flag);

lv_coord_t draw_area_width = lv_area_get_width(dsc->draw_area);

//Check if the area in which the text must be rendered is big enough
// there should be NO line breaks!
if (size.x > draw_area_width) {
  dsc->label_dsc->align = LV_TEXT_ALIGN_LEFT;
  dsc->label_dsc->flag = LV_TEXT_FLAG_EXPAND;
            
  lv_coord_t delta_offset = size.x - draw_area_width;
  static int8_t number_of_steps[3] = { 0, 0, 0};
  static uint8_t direction = 1;
  lv_coord_t offset = (size.x / delta_offset);

  if (direction == 0) {
    if ((number_of_steps[col] * offset) > draw_area_width/2) {
      direction = 1;
      number_of_steps[col]--;
    }
    else {
      number_of_steps[col]++;
    }
   }
else {
  if ((number_of_steps[col] * offset) < -draw_area_width/2) {
   direction = 0;
   number_of_steps[col]++;
  }
  else {
    number_of_steps[col]--;
   }
  }
  dsc->label_dsc->ofs_x = number_of_steps[col] * offset;
}

But now I cannot reduce the row height keeping it equal to the others and how to add a sort of separation between the cells?
When the text scrolls there is a moment in which the two cells content seems a single long string.

Ideas?

The project has been tested on the simulator and it works properly. Porting it on the embedded it does not work!

Thank you.

Hi,

For simple cropping you do
lv_table_add_cell_ctrl(table, col, row, LV_TABLE_CELL_CTRL_TEXT_CROP);

If you don’t have many data (i.e. cells) you might consider building up the table from labels which support scrolling out of the box.

The table is very simple by design to be very memory effective. Therefore it can’t handle only static texts.

LV_EVENT_DRAW_PART_BEGIN is a good idea for workaround.

Why? What happens?
Do you see something with a debugger?

Hi,

thank you.
Simple cropping works well now.

Unfortunately I am working with a big project and I cannot create a tables with labels, both for a relevant number of fields and to reduce the memory footprint.

I have tried to reproduce the code of “draw_main” in the lv_label.c in order to add a circular scroll of the text inside the cell, but without success.

I see on the debug window that the event is only called a few times on the embedded, instead of continuously as in the simulator.

I need to briefly explain what the screen looks like to add further details to its behavior description.
In a few words, there is a tile view in which the first tile is a sort of navigation tile.
While pressing on a button it switches to a second tile, and its content is updated on the go.
This tile contains a table which will change rows number against what it needs to be shown to the user.

When the second tile is loaded, the LV_EVENT_DRAW_PART_BEGIN is triggered only a few times on the embedded. On the simulator it is called continuously.
The text which needs to be scrolled is “as is”, without any modification.
When closing, and reopening the tile, the offset is applied to the text.

Summarizing, the “animation” I want to achieve as in “circular scrolling” is not working when the tile is currently shown.

I hope my problem is well explained :sweat_smile:

Thank you in advice!
@kisvegabor

I think it was working in the simulator because there disp_drv->full_refresh was enabled and the performance or memory monitor was enabled. Therefor when the indicators in the corners was updated the whole screen was update too.

You can easily solve it by creating a Timer in which you can call lv_obj_invalidate(my_table).

However I suggest using this timer to keep track of the animator state too because the call period of LV_EVENT_DRAW_PART_BEGIN is not stable. E.g. if the previous rendering took longer this even will be called later too. Or if for any reason a column in refreshed in 2 parts the event will be fired twice.

So in the timer I suggest something like this:

lv_obj_invalidate(my_table);

static uint32_t prev_call  = 0;
uint32_t elaps = lv_tick_elaps(prev_call);

//You logic comes here, with direction change and for all columns
number_of_steps[col] += elaps/10; //Increment by 1 in every 10 ms 

prev_call = lv_tick_get()

Ok!
Thank you very much for the hint!

Where do I can find a detailed LVGL guide where all the functions (e.g. lv_obj_invalidate) are explained?
I have seen that there is a lot of work/functions hidden in the code which are not explained in the examples.

More complex drawing mechanisms are explained here but it seems lv_obj_invalidate() has no direct documentation.

Anyway, it’s what is described in the comment:

1 Like