列表与网格控件¶
概述¶
这一页覆盖两类能力:
传统小规模控件:
List、Table、ButtonMatrix面向大数据集、但接口更接近 Android
ListView / GridView + ViewHolder + DataModel的高层控件:ListView、GridView
如果你的场景是“很多条目,但每个条目仍然由真实控件组成”,建议先从这里的 ListView / GridView 开始,而不是直接从 raw virtual_list / virtual_grid 起步。
只有在你需要 section / tree / page / stage、完全自定义 adapter,或者要直接面对 raw virtual 容器语义时,再继续阅读 虚拟容器与大数据集控件。
快速选型表¶
控件 |
适合场景 |
关键特点 |
|---|---|---|
|
十几条以内的简单文本列表 |
每个条目是按钮,API 最轻 |
|
大量纵向条目,条目里直接放真实控件 |
业务层主要关心 |
|
大量 tile/card,列数和高度会变化 |
业务层主要关心 |
|
小规模行列表格数据 |
直接按单元格写内容 |
|
计算器、快捷键盘、宫格按钮面板 |
在一个 view 里绘制多个按钮 |
ListView¶
ListView 是建立在 virtual_list 之上的高层包装,目标不是替代 virtual 家族,而是把常见“竖向大列表 + 真实控件行视图”的接法收敛成 Android 风格的 data_model + holder_ops。
什么时候优先用它¶
数据量较大,需要按可见区创建和回收行视图
每一行都想直接放真实控件,例如
Switch、Combobox、Button、ProgressBar业务层更想关心
ViewHolder和DataModel,不想直接写 raw adapter
最小心智模型¶
data_model负责回答“有多少条数据、stable id 是什么、view_type 是什么、高度是多少”holder_ops负责回答“这一行真实控件怎么创建、怎么绑定、怎么保存局部状态”结构变化后由业务层调用
notify_*,复用、keepalive、状态缓存和可见窗口管理交给控件内部
关键 API¶
函数 |
说明 |
|---|---|
|
一次接好 |
|
运行时替换数据模型和 holder 逻辑 |
|
在真实控件回调里反查当前 item |
|
单项内容变化但高度不变 |
|
单项高度变化 |
|
结构变化通知 |
|
设置 keepalive 上限 |
|
设置 holder 状态缓存上限 |
最小接入骨架¶
static egui_view_list_view_t list_view;
static demo_context_t demo_ctx;
EGUI_VIEW_LIST_VIEW_PARAMS_INIT(demo_params, 0, 0, 240, 320);
static const egui_view_list_view_data_model_t demo_data_model = {
.get_count = demo_get_count,
.get_stable_id = demo_get_stable_id,
.find_index_by_stable_id = demo_find_index_by_stable_id,
.get_view_type = demo_get_view_type,
.measure_item_height = demo_measure_item_height,
.default_view_type = 0,
};
static const egui_view_list_view_holder_ops_t demo_holder_ops = {
.create_holder = demo_create_holder,
.destroy_holder = demo_destroy_holder,
.bind_holder = demo_bind_holder,
.unbind_holder = demo_unbind_holder,
.save_holder_state = demo_save_holder_state,
.restore_holder_state = demo_restore_holder_state,
};
void init_ui(egui_core_t *core)
{
const egui_view_list_view_setup_t setup = {
.params = &demo_params,
.data_model = &demo_data_model,
.holder_ops = &demo_holder_ops,
.data_model_context = &demo_ctx,
.state_cache_max_entries = 8,
.state_cache_max_bytes = 64,
};
egui_view_list_view_init_with_setup(EGUI_VIEW_OF(&list_view), core, &setup);
egui_core_add_user_root_view(core, EGUI_VIEW_OF(&list_view));
}
推荐示例¶
最小例程:
example/HelloVirtual/list_view_basic/richer 场景:
example/HelloVirtual/list_view/头文件:
src/widget/egui_view_list_view.h
GridView¶
GridView 是建立在 virtual_grid 之上的高层包装,适合“很多 tile/card,但业务层只想维护 ViewHolder + DataModel”的场景。
什么时候优先用它¶
内容天然是 tile/card,而不是普通纵向 row
列数会切换,或者 tile 高度要跟随宽度变化
tile 里直接放真实控件,例如
ToggleButton、Switch、Button、ProgressBar
最小心智模型¶
data_model负责回答“总数、stable id、view_type 和每个 tile 在当前宽度下的高度”holder_ops负责创建和绑定真实 tile 视图set_column_count()、notify_*、状态缓存和复用规则都直接复用virtual_grid的成熟能力
关键 API¶
函数 |
说明 |
|---|---|
|
一次接好 |
|
运行时替换数据模型和 holder 逻辑 |
|
动态切换列数 |
|
在真实控件回调里反查当前 tile |
|
单项内容变化但高度不变 |
|
单项高度变化 |
|
结构变化通知 |
|
设置 keepalive 上限 |
|
设置 holder 状态缓存上限 |
最小接入骨架¶
static egui_view_grid_view_t grid_view;
static demo_context_t demo_ctx;
EGUI_VIEW_GRID_VIEW_PARAMS_INIT(demo_params, 0, 0, 240, 320);
static const egui_view_grid_view_data_model_t demo_data_model = {
.get_count = demo_get_count,
.get_stable_id = demo_get_stable_id,
.find_index_by_stable_id = demo_find_index_by_stable_id,
.get_view_type = demo_get_view_type,
.measure_item_height = demo_measure_item_height,
.default_view_type = 0,
};
static const egui_view_grid_view_holder_ops_t demo_holder_ops = {
.create_holder = demo_create_holder,
.destroy_holder = demo_destroy_holder,
.bind_holder = demo_bind_holder,
.unbind_holder = demo_unbind_holder,
.save_holder_state = demo_save_holder_state,
.restore_holder_state = demo_restore_holder_state,
};
void init_ui(egui_core_t *core)
{
const egui_view_grid_view_setup_t setup = {
.params = &demo_params,
.data_model = &demo_data_model,
.holder_ops = &demo_holder_ops,
.data_model_context = &demo_ctx,
.state_cache_max_entries = 8,
.state_cache_max_bytes = 64,
};
egui_view_grid_view_init_with_setup(EGUI_VIEW_OF(&grid_view), core, &setup);
egui_core_add_user_root_view(core, EGUI_VIEW_OF(&grid_view));
}
推荐示例¶
最小例程:
example/HelloVirtual/grid_view_basic/richer 场景:
example/HelloVirtual/grid_view/头文件:
src/widget/egui_view_grid_view.h
List¶
可滚动的文本列表控件,继承自 Scroll。每个列表项是一个 Button,支持点击回调。最多支持 16 个列表项。
效果展示¶
API¶
函数 |
说明 |
|---|---|
|
初始化 List |
|
使用参数初始化 |
|
添加列表项,返回索引(-1 表示已满) |
|
清空所有列表项 |
|
设置列表项高度 |
|
设置列表项点击回调 |
参数宏¶
EGUI_VIEW_LIST_PARAMS_INIT(name, x, y, w, h, item_h);
常量¶
常量 |
说明 |
|---|---|
|
最大列表项数量(默认 16) |
代码示例¶
static egui_view_list_t list;
EGUI_VIEW_LIST_PARAMS_INIT(list_params, 0, 0, 200, 150, 30);
static void on_item_click(egui_view_t *self, uint8_t index)
{
EGUI_LOG_INF("List item clicked: %d\n", index);
}
void init_ui(egui_core_t *core)
{
egui_view_list_init_with_params(
EGUI_VIEW_OF(&list), core, &list_params);
egui_view_list_add_item(EGUI_VIEW_OF(&list), "Settings");
egui_view_list_add_item(EGUI_VIEW_OF(&list), "Display");
egui_view_list_add_item(EGUI_VIEW_OF(&list), "Sound");
egui_view_list_add_item(EGUI_VIEW_OF(&list), "Network");
egui_view_list_add_item(EGUI_VIEW_OF(&list), "About");
egui_view_list_set_on_item_click(
EGUI_VIEW_OF(&list), on_item_click);
egui_core_add_user_root_view(core, EGUI_VIEW_OF(&list));
}
Table¶
表格控件,支持表头行、网格线、自定义行高和颜色。最多支持 16 行 8 列。
效果展示¶
API¶
函数 |
说明 |
|---|---|
|
初始化 Table |
|
使用参数初始化 |
|
设置单元格文本 |
|
设置行列数 |
|
设置表头行数 |
|
设置行高 |
|
显示/隐藏网格线 |
|
设置表头背景色 |
|
设置网格线颜色 |
参数宏¶
EGUI_VIEW_TABLE_PARAMS_INIT(name, x, y, w, h, row_count, col_count);
常量¶
常量 |
说明 |
|---|---|
|
最大行数(默认 16) |
|
最大列数(默认 8) |
代码示例¶
static egui_view_table_t table;
EGUI_VIEW_TABLE_PARAMS_INIT(table_params, 0, 0, 200, 120, 4, 3);
void init_ui(egui_core_t *core)
{
egui_view_table_init_with_params(
EGUI_VIEW_OF(&table), core, &table_params);
egui_view_table_set_header_rows(EGUI_VIEW_OF(&table), 1);
egui_view_table_set_row_height(EGUI_VIEW_OF(&table), 28);
egui_view_table_set_show_grid(EGUI_VIEW_OF(&table), 1);
// 表头
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 0, 0, "Name");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 0, 1, "Value");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 0, 2, "Unit");
// 数据行
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 1, 0, "Temp");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 1, 1, "25");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 1, 2, "C");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 2, 0, "Humi");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 2, 1, "60");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 2, 2, "%");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 3, 0, "Press");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 3, 1, "1013");
egui_view_table_set_cell(EGUI_VIEW_OF(&table), 3, 2, "hPa");
egui_core_add_user_root_view(core, EGUI_VIEW_OF(&table));
}