# Table (lv_table) (/widgets/table)



Overview [#overview]

A Table is a grid of rows, columns, and text cells. It is lightweight
because no widgets are created for the cells — they are drawn on the fly.

Tables are added to the default group (if one is set). A Table is an
editable widget: cells can be selected with encoder or keyboard input as
well as with a pointer.

Set cell value [#set-cell-value]

<LvglExample name="lv_example_table_cells" path="widgets/table/lv_example_table_cells" />

<ApiLink name="lv_table_set_cell_value" display="lv_table_set_cell_value(table, row, col, &#x22;Content&#x22;)" /> writes a cell.
The text is copied so the source buffer can be local. Use `\n` for a
line break inside a cell. Writing past the current grid grows the
table automatically.

Rows and Columns [#rows-and-columns]

<LvglExample name="lv_example_table_rows_columns" path="widgets/table/lv_example_table_rows_columns" />

Pre-size the grid with <ApiLink name="lv_table_set_row_count" display="lv_table_set_row_count(table, n)" /> and
<ApiLink name="lv_table_set_column_count" display="lv_table_set_column_count(table, n)" />.

Width and Height [#width-and-height]

<LvglExample name="lv_example_table_width" path="widgets/table/lv_example_table_width" />

<ApiLink name="lv_table_set_column_width" display="lv_table_set_column_width(table, col, w)" /> sets per-column pixel width;
the table's overall width is the sum. Height is derived automatically
from cell styles (font, padding) and row count.

Merge cells [#merge-cells]

<LvglExample name="lv_example_table_merge_cells" path="widgets/table/lv_example_table_merge_cells" />

<ApiLink name="lv_table_set_cell_ctrl" display="lv_table_set_cell_ctrl(table, row, col, LV_TABLE_CELL_CTRL_MERGE_RIGHT)" />

extends a cell into the next column. Chain it on adjacent cells to span
more than two columns.

Styling [#styling]

* <ApiLink name="LV_PART_MAIN" /> The background of the Table; uses the [typical
  background style properties](/common-widget-features/styles/overview).
* <ApiLink name="LV_PART_ITEMS" /> The cells of the Table also use the
  [typical background style properties](/common-widget-features/styles/overview) as well as text
  style properties.

<LvglExample name="lv_example_table_styling" path="widgets/table/lv_example_table_styling" />

Table has two stylable parts: <ApiLink name="LV_PART_MAIN" /> (the table's
outer frame and background) and <ApiLink name="LV_PART_ITEMS" /> (every
cell — borders, padding, text). Attach a named style with
`selector="main"` or `selector="items"`; cells inherit the items style
uniformly. Per-row styling isn't expressed through XML selectors today —
use cell `ctrl` flags or a runtime draw event to vary the header row.

Scrolling [#scrolling]

If a Table's width or height is set to <ApiLink name="LV_SIZE_CONTENT" /> that size
will be used to show the whole Table in the respective direction. E.g.

<ApiLink name="lv_obj_set_size" display="lv_obj_set_size(table, LV_SIZE_CONTENT, LV_SIZE_CONTENT)" />

automatically sets the Table size to show all columns and rows.

If the width or height is set to a smaller number than its "intrinsic"
size then the Table becomes scrollable.

<LvglExample name="lv_example_table_scroll" path="widgets/table/lv_example_table_scroll" />

Set cell user data [#set-cell-user-data]

<ApiLink name="lv_table_set_cell_user_data" display="lv_table_set_cell_user_data(table, row, col, ptr)" /> attaches an opaque
pointer to a cell, retrievable with <ApiLink name="lv_table_get_cell_user_data" />. The
table doesn't own the pointer — free it yourself on <ApiLink name="LV_EVENT_DELETE" /> if
the data was dynamically allocated:

```c title=" " lineNumbers=1
static void table_delete_cb(lv_event_t * e) {
    lv_obj_t * table = lv_event_get_target_obj(e);
    for(uint32_t r = 0; r < lv_table_get_row_count(table); r++) {
        for(uint32_t c = 0; c < lv_table_get_column_count(table); c++) {
            lv_free(lv_table_get_cell_user_data(table, r, c));
        }
    }
}
lv_obj_add_event_cb(table, table_delete_cb, LV_EVENT_DELETE, NULL);
```

Events [#events]

<ApiLink name="LV_EVENT_VALUE_CHANGED" /> is sent when a new cell is selected with keys.

Learn more about [Events](/common-widget-features/events) emitted by all Widgets.

Keys [#keys]

`LV_KEY_RIGHT/LEFT/UP/DOWN` selects a cell.

Note that, as usual, the state of <ApiLink name="LV_KEY_ENTER" /> is translated to
`LV_EVENT_PRESSED/PRESSING/RELEASED` etc.

<ApiLink name="lv_table_get_selected_cell" display="lv_table_get_selected_cell(table, &row, &col)" /> can be used to get the
currently selected cell. Row and column will be set to
<ApiLink name="LV_TABLE_CELL_NONE" /> if no cell is selected.

Learn more about [Keys](/main-modules/indev/keypad).

Building a file explorer [#building-a-file-explorer]

<LvglExample name="lv_example_table_file_browser" path="widgets/table/lv_example_table_file_browser" />

A table can also be used to create a simple file explorer. In the example the table has 2 columns:
a shorter one for an icon, and a longer one for the file/folder name.

The contents of a directory are listed with the [`lv_fs`](/main-modules/fs) APIs
(`lv_fs_dir_open`/`lv_fs_dir_read`/`lv_fs_dir_close`). Note that a file-system driver
(e.g. <ApiLink name="LV_USE_FS_STDIO" />) needs to be enabled in `lv_conf.h`.

The example also contains a few extra features, like a quick access sidebar.

Examples [#examples]

Scrollable 200-item list with per-row toggle [#scrollable-200-item-list-with-per-row-toggle]

It builds a 200-row table inside a scrollable parent, attaches an
<ApiLink name="LV_EVENT_DRAW_TASK_ADDED" /> callback that paints a switch-style
toggle in the second column based on the row's `CUSTOM_1` cell control flag,
and toggles that flag from <ApiLink name="LV_EVENT_VALUE_CHANGED" />.

<LvglExample name="lv_example_table_scrollable_list" path="widgets/table/lv_example_table_scrollable_list" />
