Grid(网格布局)
Overview(概述)
显示原文
The Grid layout is a subset of CSS Grid layout.
It can arrange items (child Widgets) into a 2D "table" that has rows and columns
(tracks). An item can span multiple columns or rows. The
track's size can be set in pixels, to the largest item
(LV_GRID_CONTENT
), or to a fraction of the available free space
(i.e. Free [FR] Units) to distribute free space proportionally.
To make a Widget a Grid container call lv_obj_set_layout(widget, LV_LAYOUT_GRID).
Note that the Grid layout feature of LVGL needs to be globally enabled
with LV_USE_GRID
in lv_conf.h
.
Grid(网格布局)是 CSS Grid 的一个子集。
它可以将元素排列成具有行或列(轨道)的二维 “表格” 中。该元素可以跨越多个列或行。轨道的大小可以设置为像素、最大元素(LV_GRID_CONTENT
)或 “空闲单元” (FR) 以按比例分配自由空间。
要使对象成为网格容器,请调用函数 lv_obj_set_layout(obj, LV_LAYOUT_GRID) 设置。
请注意,LVGL 的 Grid(网格布局)功能需要打开 lv_conf.h
中的宏 LV_USE_GRID
启用。
Terms(约定)
显示原文
tracks: rows or columns
free (FR) units: if a track's size is set in
FR units
it will grow to fill the remaining space in the parent Widget (container), in proportion with other tracks that have non-zero FR-unit values.gap: the space between rows and columns or the items on a track
tracks: 行或列
free (FR) units: 如果一个轨道的大小设置为
FR units
,它会根据其他具有非零 FR-unit 值的轨道,按比例填充父级 Widget(容器)中的剩余空间。gap: 行与列之间的空间,或者轨道上项之间的间距
Simple Interface(简单的接口)
显示原文
With the following functions you can cause any parent Widget to have Grid-layout behaviors.
备注
As with Flex containers, the parent Widget must be a Grid container for these styles to take effect. The functions below cause the parent Widget to become a Grid container if it is not already.
使用以下函数可以使任何父级 Widget 具有 Grid-layout 行为。
备注
与 Flex 容器一样,父级 Widget 必须是 Grid 容器,才能使这些样式生效。 下面的函数会使父级 Widget 成为 Grid 容器(如果它还不是的话)。
Grid descriptors(网格描述符)
显示原文
First you need to describe the size of rows and columns. It can be done
by declaring 2 arrays and the track sizes in them. The last element must
be LV_GRID_TEMPLATE_LAST
.
For example:
static int32_t column_dsc[] = {100, 400, LV_GRID_TEMPLATE_LAST}; /* 2 columns with 100- and 400-px width */
static int32_t row_dsc[] = {100, 100, 100, LV_GRID_TEMPLATE_LAST}; /* 3 100-px tall rows */
To set the descriptors on a parent use lv_obj_set_grid_dsc_array(widget, col_dsc, row_dsc).
Besides settings the sizes in pixels, you can use two special values:
LV_GRID_CONTENT
sets size to fit the largest child on this trackLV_GRID_FR(X) determines what portion of the remaining space should be used by this track. Larger values means larger space.
首先,你需要描述行和列的大小。这可以通过声明 2 个数组并在其中定义轨道大小来完成。
最后一个元素必须是 LV_GRID_TEMPLATE_LAST
。
例如:
static int32_t column_dsc[] = {100, 400, LV_GRID_TEMPLATE_LAST}; /* 2 列,宽度分别为 100 像素和 400 像素 */
static int32_t row_dsc[] = {100, 100, 100, LV_GRID_TEMPLATE_LAST}; /* 3 行,每行高度为 100 像素 */
要在父级上设置描述符,使用 lv_obj_set_grid_dsc_array(widget, col_dsc, row_dsc)。
除了设置像素大小外,你还可以使用两个特殊值:
LV_GRID_CONTENT
设置大小以适应此轨道上最大的子项LV_GRID_FR(X) 确定此轨道应使用剩余空间的哪一部分。值越大,占用的空间越大。
Grid items(网格项)
显示原文
By default, a Widget's children are not added to the grid. They need to be added manually to a cell.
To do this call lv_obj_set_grid_cell(child, column_align, column_pos, column_span, row_align, row_pos, row_span).
column_align
and row_align
determine how to align the child Widget
in its cell. Possible values are:
LV_GRID_ALIGN_START
: means left when direction is horizontal and top when vertical (default)LV_GRID_ALIGN_END
: means right when direction is horizontal and bottom when verticalLV_GRID_ALIGN_CENTER
: simply centercolumn_pos
androw_pos
means the zero-based index of the cell in which the item should be placed.
column_span
and row_span
means how many tracks should be occupied
from the start cell. Must be >= 1
.
默认情况下,小部件的子项不会添加到网格中。需要手动将它们添加到单元格中。
为此,调用: lv_obj_set_grid_cell(child, column_align, column_pos, column_span, row_align, row_pos, row_span)。
column_align
和 row_align
决定了子小部件在其单元格中的对齐方式。可能的值有:
LV_GRID_ALIGN_START
:当方向为水平时,表示左对齐,当方向为垂直时,表示上对齐(默认值)LV_GRID_ALIGN_END
:当方向为水平时,表示右对齐,当方向为垂直时,表示下对齐LV_GRID_ALIGN_CENTER
:简单地将column_pos
和row_pos
居中,表示该项应放置的单元格的零基索引。
column_span
和 row_span
表示从起始单元格开始应该占据多少轨道。必须是 >= 1
。
Grid align(对齐方式)
显示原文
If there is some empty space, items (Widgets) in Grid tracks can be aligned in several ways:
LV_GRID_ALIGN_START
: means left when direction is horizontal and top when vertical. (default)LV_GRID_ALIGN_END
: means right when direction is horizontal and bottom when verticalLV_GRID_ALIGN_CENTER
: simply centerLV_GRID_ALIGN_SPACE_EVENLY
: items are distributed so that the spacing between any two items (and the space to the edges) is equal. Not applies totrack_cross_place
.LV_GRID_ALIGN_SPACE_AROUND
: items are evenly distributed in the track with equal space around them. Note that visually the spaces aren't equal, since all the items have equal space on both sides. This makes the space between items double the space between edge items and the container's edge. Does not apply totrack_cross_place
.LV_GRID_ALIGN_SPACE_BETWEEN
: items are evenly distributed in the track with first and last items next to container's edges. Does not apply totrack_cross_place
.
To set the track's alignment use lv_obj_set_grid_align(widget, column_align, row_align).
如果有一些空余空间,Grid 轨道中的项(Widgets)可以通过以下几种方式对齐:
LV_GRID_ALIGN_START
:当方向为水平方向时表示左对齐,当方向为垂直方向时表示上对齐。(默认)LV_GRID_ALIGN_END
:当方向为水平方向时表示右对齐,当方向为垂直方向时表示下对齐LV_GRID_ALIGN_CENTER
:简单的居中对齐LV_GRID_ALIGN_SPACE_EVENLY
:项均匀分布,使得任意两个项之间的间距(以及与边缘的空间)相等。不适用于track_cross_place
。LV_GRID_ALIGN_SPACE_AROUND
:项在轨道中均匀分布,四周有相等的空间。请注意,视觉上空间不完全相等,因为所有项在两侧的空间相等。这使得项之间的空间是边缘项与容器边缘之间空间的两倍。不适用于track_cross_place
。LV_GRID_ALIGN_SPACE_BETWEEN
:项在轨道中均匀分布,首尾项紧邻容器的边缘。不适用于track_cross_place
。
要设置轨道的对齐方式,请使用 lv_obj_set_grid_align(widget, column_align, row_align)。
Sub grid(子网格)
显示原文
If you set the column and/or row grid descriptors of a widget to NULL
it will use
the grid descriptor(s) from it's parent.
For example if you create a grid item that spans columns 2..6 columns and rows 1..3 of the grid, the grid item will occupy 5 columns and 4 rows with the corresponding track size from the parent Grid container.
This way even if a wrapper item is used in the grid, it can be made "transparent" from the grid's point of view.
Limitations:
The sub-grid is resolved only to a depth of 1 level. That is, a grid can have a sub-grid child, but that sub-grid cannot have another sub-grid.
LV_GRID_CONTENT
tracks on the grid are not handled in the sub-grid, only in its own grid.
The sub-grid feature works the same as in CSS. For further information, see CSS Subgrid.
如果您将小部件的列和/或行网格描述符设置为 NULL
,它将使用其父级的网格描述符。
例如,如果您创建一个跨越列 2..6 和行 1..3 的网格项,该网格项将占据 5 列和 4 行,并使用父级网格容器中相应的轨道大小。
通过这种方式,即使在网格中使用了包装项,它也可以从网格的角度来看是“透明的”。
限制:
子网格的解析深度仅为 1 层。也就是说,网格可以有一个子网格子项,但该子网格不能有另一个子网格。
LV_GRID_CONTENT
网格上的轨道在子网格中不处理,只在其自身的网格中处理。
子网格功能与 CSS 中的工作方式相同。如需进一步参考请参阅 这里的说明.
Style interface(样式接口)
显示原文
All the Grid related values are style properties under the hood and you can use them similarly to any other style properties.
The following Grid related style properties exist:
GRID_COLUMN_DSC_ARRAY
GRID_ROW_DSC_ARRAY
GRID_COLUMN_ALIGN
GRID_ROW_ALIGN
GRID_CELL_X_ALIGN
GRID_CELL_COLUMN_POS
GRID_CELL_COLUMN_SPAN
GRID_CELL_Y_ALIGN
GRID_CELL_ROW_POS
GRID_CELL_ROW_SPAN
所有与 Grid 相关的值都是底层的样式属性,可以像使用任何其他样式属性那样使用它们。
下面是与网格相关的样式属性:
GRID_COLUMN_DSC_ARRAY
GRID_ROW_DSC_ARRAY
GRID_COLUMN_ALIGN
GRID_ROW_ALIGN
GRID_CELL_X_ALIGN
GRID_CELL_COLUMN_POS
GRID_CELL_COLUMN_SPAN
GRID_CELL_Y_ALIGN
GRID_CELL_ROW_POS
GRID_CELL_ROW_SPAN
Internal padding(内部填充)
显示原文
To modify the minimum space Grid inserts between Widgets, the following properties can be set on the Grid container style:
lv_style_set_pad_row()
sets padding between rows.lv_style_set_pad_column()
sets padding between columns.
要修改网格布局中对象之间的间隔,可以在给网格布局的容器修改下面所示的样式属性:
lv_style_set_pad_row()
设置行之间的填充。lv_style_set_pad_column()
设置列之间的填充。
Other features(其它功能)
RTL
显示原文
If the base direction of the container is set to LV_BASE_DIR_RTL
,
the meaning of LV_GRID_ALIGN_START
and LV_GRID_ALIGN_END
is
swapped. I.e. START
will mean right-most.
The columns will be placed from right to left.
Further Reading
Learn more about CSS Grid layout.
Learn more about CSS Subgrid layout.
如果容器的基础方向设置为:cpp:enumerator:LV_BASE_DIR_RTL,则:cpp:enumerator:`LV_GRID_ALIGN_START`和:cpp:enumerator:`LV_GRID_ALIGN_END`的含义将被交换。也就是说,``START``将表示最右侧。
列将从右到左排列。
进一步阅读
了解更多关于 CSS Grid 布局。
了解更多关于 CSS Subgrid 布局。
Example
A simple grid
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
/**
* A simple grid
*/
void lv_example_grid_1(void)
{
static int32_t col_dsc[] = {70, 70, 70, LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {50, 50, 50, LV_GRID_TEMPLATE_LAST};
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0);
lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0);
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_set_layout(cont, LV_LAYOUT_GRID);
lv_obj_t * label;
lv_obj_t * obj;
uint32_t i;
for(i = 0; i < 9; i++) {
uint8_t col = i % 3;
uint8_t row = i / 3;
obj = lv_button_create(cont);
/*Stretch the cell horizontally and vertically too
*Set span to 1 to make the cell 1 column/row sized*/
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "c%d, r%d", col, row);
lv_obj_center(label);
}
}
#endif
Demonstrate cell placement and span
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
/**
* Demonstrate cell placement and span
*/
void lv_example_grid_2(void)
{
static int32_t col_dsc[] = {70, 70, 70, LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {50, 50, 50, LV_GRID_TEMPLATE_LAST};
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_t * label;
lv_obj_t * obj;
/*Cell to 0;0 and align to to the start (left/top) horizontally and vertically too*/
obj = lv_obj_create(cont);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_START, 0, 1,
LV_GRID_ALIGN_START, 0, 1);
label = lv_label_create(obj);
lv_label_set_text(label, "c0, r0");
/*Cell to 1;0 and align to to the start (left) horizontally and center vertically too*/
obj = lv_obj_create(cont);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_START, 1, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
label = lv_label_create(obj);
lv_label_set_text(label, "c1, r0");
/*Cell to 2;0 and align to to the start (left) horizontally and end (bottom) vertically too*/
obj = lv_obj_create(cont);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_START, 2, 1,
LV_GRID_ALIGN_END, 0, 1);
label = lv_label_create(obj);
lv_label_set_text(label, "c2, r0");
/*Cell to 1;1 but 2 column wide (span = 2).Set width and height to stretched.*/
obj = lv_obj_create(cont);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, 1, 2,
LV_GRID_ALIGN_STRETCH, 1, 1);
label = lv_label_create(obj);
lv_label_set_text(label, "c1-2, r1");
/*Cell to 0;1 but 2 rows tall (span = 2).Set width and height to stretched.*/
obj = lv_obj_create(cont);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, 0, 1,
LV_GRID_ALIGN_STRETCH, 1, 2);
label = lv_label_create(obj);
lv_label_set_text(label, "c0\nr1-2");
}
#endif
Demonstrate grid's -free unit-
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
/**
* Demonstrate grid's "free unit"
*/
void lv_example_grid_3(void)
{
/*Column 1: fix width 60 px
*Column 2: 1 unit from the remaining free space
*Column 3: 2 unit from the remaining free space*/
static int32_t col_dsc[] = {60, LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST};
/*Row 1: fix width 50 px
*Row 2: 1 unit from the remaining free space
*Row 3: fix width 50 px*/
static int32_t row_dsc[] = {50, LV_GRID_FR(1), 50, LV_GRID_TEMPLATE_LAST};
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
lv_obj_t * label;
lv_obj_t * obj;
uint32_t i;
for(i = 0; i < 9; i++) {
uint8_t col = i % 3;
uint8_t row = i / 3;
obj = lv_obj_create(cont);
/*Stretch the cell horizontally and vertically too
*Set span to 1 to make the cell 1 column/row sized*/
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%d,%d", col, row);
lv_obj_center(label);
}
}
#endif
Demonstrate track placement
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
/**
* Demonstrate track placement
*/
void lv_example_grid_4(void)
{
static int32_t col_dsc[] = {60, 60, 60, LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {45, 45, 45, LV_GRID_TEMPLATE_LAST};
/*Add space between the columns and move the rows to the bottom (end)*/
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_grid_align(cont, LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_END);
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_t * label;
lv_obj_t * obj;
uint32_t i;
for(i = 0; i < 9; i++) {
uint8_t col = i % 3;
uint8_t row = i / 3;
obj = lv_obj_create(cont);
/*Stretch the cell horizontally and vertically too
*Set span to 1 to make the cell 1 column/row sized*/
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%d,%d", col, row);
lv_obj_center(label);
}
}
#endif
Demonstrate column and row gap
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
static void row_gap_anim(void * obj, int32_t v)
{
lv_obj_set_style_pad_row(obj, v, 0);
}
static void column_gap_anim(void * obj, int32_t v)
{
lv_obj_set_style_pad_column(obj, v, 0);
}
/**
* Demonstrate column and row gap
*/
void lv_example_grid_5(void)
{
/*60x60 cells*/
static int32_t col_dsc[] = {60, 60, 60, LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {45, 45, 45, LV_GRID_TEMPLATE_LAST};
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
lv_obj_t * label;
lv_obj_t * obj;
uint32_t i;
for(i = 0; i < 9; i++) {
uint8_t col = i % 3;
uint8_t row = i / 3;
obj = lv_obj_create(cont);
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%d,%d", col, row);
lv_obj_center(label);
}
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, cont);
lv_anim_set_values(&a, 0, 10);
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
lv_anim_set_exec_cb(&a, row_gap_anim);
lv_anim_set_duration(&a, 500);
lv_anim_set_playback_duration(&a, 500);
lv_anim_start(&a);
lv_anim_set_exec_cb(&a, column_gap_anim);
lv_anim_set_duration(&a, 3000);
lv_anim_set_playback_duration(&a, 3000);
lv_anim_start(&a);
}
#endif
Demonstrate RTL direction on grid
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_GRID && LV_BUILD_EXAMPLES
/**
* Demonstrate RTL direction on grid
*/
void lv_example_grid_6(void)
{
static int32_t col_dsc[] = {60, 60, 60, LV_GRID_TEMPLATE_LAST};
static int32_t row_dsc[] = {45, 45, 45, LV_GRID_TEMPLATE_LAST};
/*Create a container with grid*/
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 300, 220);
lv_obj_center(cont);
lv_obj_set_style_base_dir(cont, LV_BASE_DIR_RTL, 0);
lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
lv_obj_t * label;
lv_obj_t * obj;
uint32_t i;
for(i = 0; i < 9; i++) {
uint8_t col = i % 3;
uint8_t row = i / 3;
obj = lv_obj_create(cont);
/*Stretch the cell horizontally and vertically too
*Set span to 1 to make the cell 1 column/row sized*/
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1,
LV_GRID_ALIGN_STRETCH, row, 1);
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%d,%d", col, row);
lv_obj_center(label);
}
}
#endif