写的页面架构
This commit is contained in:
+133
-152
@@ -1,13 +1,21 @@
|
||||
/*
|
||||
* 模块名称:UI Content Page (内容页面显示层)
|
||||
* 模块功能:菜单叶子节点的内容页(装置信息/交流量/直流量)——独立 LVGL 屏幕,
|
||||
* 全屏容器 DRAW_MAIN 自绘全部内容(浅 V 装饰 + 居中标题 + 行数据 +
|
||||
* 页脚页码),无子对象;进入时切屏并获焦、ESC 返回菜单屏并还原焦点
|
||||
* 模块名称:UI Content Page (内容页框架)
|
||||
* 模块功能:菜单叶子节点进入的内容页(独立全屏页面)框架——全屏容器
|
||||
* 自绘全部内容(浅 V 装饰 + 居中标题 + 行数据 + 页脚页码),无子对象;
|
||||
* 只持机制:屏/容器按需建毁、焦点、按键分发、描述符驱动通用绘制;
|
||||
* 不持任何页面数据——各页数据/几何/钩子由 ui_page_xxx 模块经
|
||||
* content_page_def_t 接入描述符表 s_defs[](架构见 内容页架构.md);
|
||||
* 进入时切屏并获焦、ESC 返回菜单屏并还原焦点;
|
||||
* 不持有导航状态——由逻辑层 ui_menu.c 在 ENTER 叶子节点时驱动
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-09
|
||||
* 修改记录:
|
||||
* 2026-09-09 王建锋 创建:装置信息/交流量/直流量三页(参考图 10/20/21 实测几何)
|
||||
* 2026-09-09 王建锋 "浅 V"装饰几何提取至共享 ui_deco 模块(不再本地重复定义)
|
||||
* 2026-09-09 王建锋 拆分为"框架 + 页面插件"模型(内容页架构.md):三页数据移入
|
||||
* ui_page_xxx 模块,本文件只留机制 + 描述符表;绘制/按键改
|
||||
* 按描述符驱动(静态表/refresh + 4 钩子),行为零变化
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
@@ -15,8 +23,16 @@
|
||||
|
||||
#include "ui_content_page.h"
|
||||
|
||||
#include "ui_page_device_info.h"
|
||||
|
||||
#include "ui_page_ac.h"
|
||||
|
||||
#include "ui_page_dc.h"
|
||||
|
||||
#include "ui_menu_view.h"
|
||||
|
||||
#include "ui_deco.h"
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
#define DBG_TAG "[UI_CONTENT_PAGE]"
|
||||
@@ -27,8 +43,6 @@
|
||||
/*
|
||||
* 布局常量(设备像素;参考图 10/20/21 实测,3x 放大图缩回 160x160 测量):
|
||||
* 标题 y=2(CJK 字形顶距 +1 → 墨迹自 y=3 起,与参考图一致)、页脚 y=143;
|
||||
* 信息页行:首行 y=40、行距 15、标签列 x=6 / 值列 x=86(无选中带);
|
||||
* 列表页行:槽顶 = 24+14i、选中白带 x=2..156 高 13、名 x=7 / 值 x=101;
|
||||
* 字形顶距(CJK +1 / ASCII +2)已计入放置 y,墨迹与参考图对齐
|
||||
*/
|
||||
#define CP_SCREEN_W 160 /* 屏幕宽(px,与 ui_port.h / 模拟器一致) */
|
||||
@@ -37,106 +51,18 @@
|
||||
#define CP_TITLE_Y 2 /* 标题放置 y(居中;墨迹自 y=3 起) */
|
||||
#define CP_PAGE_LINE_Y 143 /* 页脚"第 X 页,共 Y 页"放置 y(x=6 左对齐) */
|
||||
|
||||
#define CP_DECO_LEG_W 3 /* "浅 V"两腿线宽(与菜单根框一致:1bpp 斜线须加粗) */
|
||||
#define CP_DECO_HORIZ_W 2 /* "浅 V"水平线宽 */
|
||||
|
||||
/* 私有类型定义区 */
|
||||
|
||||
/* 行数据:左列名 + 右列值(Flash 字面量,不 strdup) */
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *value;
|
||||
} cp_row_t;
|
||||
|
||||
/*
|
||||
* 页面定义(Flash 常量表):标题/行几何/数据表/页脚参数;
|
||||
* selectable=1 为可移选分页的数据列表页,0 为静态信息页
|
||||
*/
|
||||
typedef struct {
|
||||
const char *title; /* 标题(浅 V 区居中) */
|
||||
uint8_t selectable; /* 1 = 数据列表页(↑↓移选/分页);0 = 信息页(静态行) */
|
||||
int32_t top_y; /* 首行槽顶 y */
|
||||
int32_t pitch; /* 行距(相邻行槽顶间距) */
|
||||
int32_t band_h; /* 选中白带高(0 = 无选中带) */
|
||||
int32_t text_dy; /* 文本放置相对行槽顶的垂直偏移 */
|
||||
int32_t left_x; /* 左列 x(信息页=标签、列表页=名) */
|
||||
int32_t right_x; /* 右列 x(值) */
|
||||
uint8_t rows_per_page; /* 每页可见行数(0 = 不分页) */
|
||||
uint16_t total_rows; /* 数据总行数 */
|
||||
const cp_row_t *rows; /* 数据表(Flash) */
|
||||
const char *subtitle; /* 副标题(居中;NULL = 无,仅信息页有) */
|
||||
int32_t subtitle_y; /* 副标题放置 y(-1 = 无) */
|
||||
uint8_t fixed_cur_page; /* 页脚"第 X 页"固定显示值(信息页按参考图原样) */
|
||||
uint8_t fixed_total_pages; /* 页脚"共 Y 页"固定显示值 */
|
||||
} cp_def_t;
|
||||
#define CP_ROW_BUF_LEN 32 /* 动态行栈缓冲长度(同帧同步光栅化;超出行带即被裁切) */
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
/* "浅 V"装饰点集与线宽:几何与菜单根框一致(ui_menu_view.c s_deco_*),culling 区同范围 */
|
||||
static const lv_point_precise_t s_deco_leg_l[2] = { {7, 7}, {16, 17} }; /* 左腿 */
|
||||
static const lv_point_precise_t s_deco_hoz[2] = { {16, 17}, {145, 17} }; /* 水平线:接两腿底端 */
|
||||
static const lv_point_precise_t s_deco_leg_r[2] = { {158, 7}, {145, 17} }; /* 右腿 */
|
||||
static const lv_point_precise_t *const s_deco_segs[3] = {s_deco_leg_l, s_deco_leg_r, s_deco_hoz};
|
||||
static const int32_t s_deco_seg_w[3] = {CP_DECO_LEG_W, CP_DECO_LEG_W, CP_DECO_HORIZ_W};
|
||||
|
||||
static const lv_area_t s_deco_band = {0, 0, CP_SCREEN_W - 1, 19}; /* 浅 V culling 区 */
|
||||
|
||||
/* 装置信息行(参考图 10;标签含全角冒号,值列固定 x=86) */
|
||||
static const cp_row_t s_info_rows[] = {
|
||||
{"终端类型:", "F30"},
|
||||
{"终端型号:", "F30"},
|
||||
{"软件版本:", "SV0.010"},
|
||||
{"硬件版本:", "HW0.010"},
|
||||
{"软件校验:", "4454"},
|
||||
{"程序日期:", "2024.08.27"},
|
||||
};
|
||||
|
||||
/* 交流量行(参考图 20 = 第 1 页原样;第 2/3 页为占位数据,可替换) */
|
||||
static const cp_row_t s_ac_rows[] = {
|
||||
{"Ia1", "0.000"}, /* 第 1 页(参考图 20) */
|
||||
{"Ib1", "0.137"},
|
||||
{"Ic1", "0.274"},
|
||||
{"Ia2", "0.411"},
|
||||
{"Ib2", "0.548"},
|
||||
{"Ic2", "0.685"},
|
||||
{"Ua1", "0.82"},
|
||||
{"Ub1", "0.96"},
|
||||
{"Uc1", "1.03"}, /* 第 2 页(占位数据) */
|
||||
{"Uab", "1.17"},
|
||||
{"Ubc", "1.24"},
|
||||
{"Uca", "1.31"},
|
||||
{"Hz", "50.00"},
|
||||
{"P", "1.42"},
|
||||
{"Q", "0.87"},
|
||||
{"S", "1.63"},
|
||||
{"PF", "0.95"}, /* 第 3 页(占位数据) */
|
||||
{"Iavg","0.35"},
|
||||
{"Uavg","0.87"},
|
||||
{"Fmax","50.02"},
|
||||
{"Imax","1.24"},
|
||||
{"Pmax","2.10"},
|
||||
{"Qmax","1.05"},
|
||||
{"Smax","2.45"},
|
||||
};
|
||||
|
||||
/* 直流量行(参考图 21) */
|
||||
static const cp_row_t s_dc_rows[] = {
|
||||
{"ZL01", "3.01"},
|
||||
{"ZL02", "3.15"},
|
||||
{"Pa1", "3.288"},
|
||||
};
|
||||
|
||||
/* 页面定义表(顺序与 content_page_id_t 一致) */
|
||||
static const cp_def_t s_defs[CONTENT_PAGE_COUNT] = {
|
||||
/* 装置信息:静态键值行 + 副标题;页脚按参考图原样"第 10 页,共 1 页" */
|
||||
{"装置信息", 0u, 40, 15, 0, 0, 6, 86, 0u, (uint16_t)6, s_info_rows,
|
||||
"馈线自动化终端", 25, 10u, 1u},
|
||||
/* 交流量:24 项 / 8 项每页(3 页);text_dy=0:ASCII 字形顶距 +2,墨迹落槽顶+2(与参考图一致) */
|
||||
{"交流量", 1u, 24, 14, 13, 0, 7, 101, 8u, (uint16_t)24, s_ac_rows,
|
||||
NULL, -1, 0u, 0u},
|
||||
/* 直流量:3 项单页 */
|
||||
{"直流量", 1u, 24, 14, 13, 0, 7, 101, 8u, (uint16_t)3, s_dc_rows,
|
||||
NULL, -1, 0u, 0u},
|
||||
/*
|
||||
* 描述符表:页 ID → 页面模块描述符(每页一行;新增页 = 枚举值 + 此处一行,
|
||||
* 框架机制不变,见 内容页架构.md §七)
|
||||
*/
|
||||
static const content_page_def_t *const s_defs[CONTENT_PAGE_COUNT] = {
|
||||
[CONTENT_PAGE_DEVICE_INFO] = &ui_page_device_info_desc,
|
||||
[CONTENT_PAGE_AC] = &ui_page_ac_desc,
|
||||
[CONTENT_PAGE_DC] = &ui_page_dc_desc,
|
||||
};
|
||||
|
||||
static content_page_id_t s_open = CONTENT_PAGE_COUNT; /* 当前打开的页(COUNT = 未打开) */
|
||||
@@ -181,6 +107,20 @@ static bool cp_areas_intersect(const lv_area_t *a, const lv_area_t *b) {
|
||||
return (x1 <= x2 && y1 <= y2);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:取页面总行数(静态页 = 描述符 row_count,动态页 = count_cb)
|
||||
* 入口参数:d - 页面描述符 const content_page_def_t *
|
||||
* 返回值:总行数 uint16_t
|
||||
* 限定条件:d 非空
|
||||
* 函数说明:行数唯一入口;绘制(窗口/页脚)与按键(移选取模)均经此取
|
||||
*/
|
||||
static uint16_t cp_row_total(const content_page_def_t *d) {
|
||||
if (d->count_cb != NULL) {
|
||||
return d->count_cb();
|
||||
}
|
||||
return d->row_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:绘制居中单行文本(标题/副标题)
|
||||
* 入口参数:layer - 绘制层 lv_layer_t *
|
||||
@@ -211,34 +151,25 @@ static void cp_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:页面自绘(浅 V 装饰 + 标题/副标题 + 行数据 + 页脚页码)
|
||||
* 函数功能:页面自绘(浅 V 装饰 + 标题/副标题 + 行数据 + 页脚页码 + 页面钩子)
|
||||
* 入口参数:e - 事件指针 lv_event_t *
|
||||
* 返回值:无
|
||||
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,页面已打开
|
||||
* 函数说明: 1. 浅 V 装饰几何与菜单根框一致(3 段线逐段画)
|
||||
* 2. 列表页窗口 = 选中行所在页(首可见行 = (sel/每页数)*每页数),
|
||||
* 函数说明: 1. 浅 V 装饰:共享 ui_deco 模块(与菜单根框同几何)
|
||||
* 2. 行数:静态页取 row_count,动态页取 count_cb();
|
||||
* 列表页窗口 = 选中行所在页(首可见行 = (sel/每页数)*每页数),
|
||||
* 行槽位置固定、数据随页切换;信息页全量静态绘制
|
||||
* 3. 选中行整行白带(x=2..156)+ 黑字,非选中白字
|
||||
* 4. 各区块按 culling 区跳过不在重绘区的部分
|
||||
* 3. 行文本:静态页直绘 Flash 表(不拷内存);动态页经 refresh()
|
||||
* 逐行取入栈缓冲(同帧同步光栅化,安全)
|
||||
* 4. 选中行整行白带(x=2..156)+ 黑字,非选中白字
|
||||
* 5. 各区块按 culling 区跳过不在重绘区的部分;末尾调 draw_cb(页自定义内容)
|
||||
*/
|
||||
static void cp_draw_cb(lv_event_t *e) {
|
||||
const cp_def_t *d = &s_defs[s_open];
|
||||
const content_page_def_t *d = s_defs[s_open];
|
||||
lv_layer_t *layer = lv_event_get_layer(e);
|
||||
|
||||
/* "浅 V"装饰:3 段线(与菜单根框同几何) */
|
||||
if (cp_areas_intersect(&s_deco_band, &layer->_clip_area)) {
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
lv_draw_line_dsc_t ld;
|
||||
|
||||
lv_draw_line_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.color = lv_color_white();
|
||||
ld.width = s_deco_seg_w[i];
|
||||
ld.p1 = s_deco_segs[i][0];
|
||||
ld.p2 = s_deco_segs[i][1];
|
||||
lv_draw_line(layer, &ld);
|
||||
}
|
||||
}
|
||||
/* "浅 V"装饰:共享 ui_deco 模块(与菜单根框同几何) */
|
||||
ui_deco_draw(layer, &layer->_clip_area);
|
||||
|
||||
/* 标题(居中) */
|
||||
{
|
||||
@@ -267,17 +198,22 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
}
|
||||
|
||||
/* 行数据:列表页窗口跟随选中行所在页,信息页全量 */
|
||||
int32_t nrows = (int32_t)cp_row_total(d);
|
||||
int32_t first = 0;
|
||||
int32_t cnt = (int32_t)d->total_rows;
|
||||
int32_t cnt = nrows;
|
||||
|
||||
if (d->selectable && d->rows_per_page > 0u) {
|
||||
if (d->selectable != 0u && d->rows_per_page > 0u) {
|
||||
first = (int32_t)(s_sel / d->rows_per_page) * d->rows_per_page; /* 窗口顶行 */
|
||||
cnt = (int32_t)d->total_rows - first;
|
||||
cnt = nrows - first;
|
||||
if (cnt > (int32_t)d->rows_per_page) {
|
||||
cnt = (int32_t)d->rows_per_page; /* 末页不足整页时截断 */
|
||||
}
|
||||
}
|
||||
|
||||
bool dynamic = (d->refresh != NULL);
|
||||
char dyn_name[CP_ROW_BUF_LEN]; /* 动态行栈缓冲(同帧同步光栅化) */
|
||||
char dyn_value[CP_ROW_BUF_LEN];
|
||||
|
||||
for (int32_t i = 0; i < cnt; i++) {
|
||||
int32_t row_idx = first + i; /* 数据下标(跨页连续) */
|
||||
int32_t slot_y = d->top_y + i * d->pitch; /* 行槽顶(窗口内位置固定) */
|
||||
@@ -310,15 +246,28 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
lv_draw_rect(layer, &fd, &band);
|
||||
}
|
||||
|
||||
/* 左列(标签/名)与右列(值):固定列 x,垂直偏移 text_dy */
|
||||
/* 行文本:静态 = Flash 表(不拷内存);动态 = refresh 逐行取(栈缓冲) */
|
||||
const char *name;
|
||||
const char *value;
|
||||
|
||||
if (dynamic) {
|
||||
d->refresh((uint16_t)row_idx, dyn_name, dyn_value);
|
||||
name = dyn_name;
|
||||
value = dyn_value;
|
||||
}
|
||||
else {
|
||||
name = d->rows[row_idx].name;
|
||||
value = d->rows[row_idx].value;
|
||||
}
|
||||
|
||||
{
|
||||
lv_draw_label_dsc_t ld;
|
||||
|
||||
/* ofs_x/ofs_y 相对 coords 原点(strip.y1=slot_y),勿再叠加 slot_y */
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = d->rows[row_idx].name;
|
||||
ld.text_static = 1; /* Flash 字符串:不拷内存 */
|
||||
ld.text = name;
|
||||
ld.text_static = (uint32_t)(!dynamic); /* 静态不拷;动态缓冲同帧内有效 */
|
||||
ld.color = color; /* 选中黑 / 非选中白 */
|
||||
ld.ofs_x = d->left_x;
|
||||
ld.ofs_y = d->text_dy;
|
||||
@@ -326,8 +275,8 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = d->rows[row_idx].value;
|
||||
ld.text_static = 1;
|
||||
ld.text = value;
|
||||
ld.text_static = (uint32_t)(!dynamic);
|
||||
ld.color = color;
|
||||
ld.ofs_x = d->right_x;
|
||||
ld.ofs_y = d->text_dy;
|
||||
@@ -339,16 +288,16 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
{
|
||||
char buf[32];
|
||||
uint8_t cur;
|
||||
uint8_t total;
|
||||
uint8_t pages;
|
||||
lv_area_t t;
|
||||
|
||||
if (d->selectable) {
|
||||
if (d->selectable != 0u) {
|
||||
cur = (uint8_t)(s_sel / d->rows_per_page + 1u);
|
||||
total = (uint8_t)((d->total_rows + d->rows_per_page - 1u) / d->rows_per_page);
|
||||
pages = (uint8_t)((nrows + (int32_t)d->rows_per_page - 1) / d->rows_per_page);
|
||||
}
|
||||
else {
|
||||
cur = d->fixed_cur_page;
|
||||
total = d->fixed_total_pages;
|
||||
pages = d->fixed_total_pages;
|
||||
}
|
||||
|
||||
t.x1 = 0;
|
||||
@@ -357,7 +306,7 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
t.y2 = CP_PAGE_LINE_Y + 15;
|
||||
if (cp_areas_intersect(&t, &layer->_clip_area)) {
|
||||
/* lv_snprintf 而非 snprintf:MSVC 对 printf 族做格式串扫描,中文字面量会误报 C4819 */
|
||||
lv_snprintf(buf, sizeof(buf), "第 %u 页,共 %u 页", (unsigned)cur, (unsigned)total);
|
||||
lv_snprintf(buf, sizeof(buf), "第 %u 页,共 %u 页", (unsigned)cur, (unsigned)pages);
|
||||
|
||||
lv_draw_label_dsc_t ld;
|
||||
|
||||
@@ -371,38 +320,64 @@ static void cp_draw_cb(lv_event_t *e) {
|
||||
lv_draw_label(layer, &ld, &t);
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面钩子:自定义内容(表单/操作页;在内置区块之后绘制) */
|
||||
if (d->draw_cb != NULL) {
|
||||
d->draw_cb(layer, &layer->_clip_area);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:页面按键事件入口(↑↓移选 / ESC·←返回)
|
||||
* 函数功能:页面按键事件入口(↑↓移选 / ESC·←返回 / 页面钩子)
|
||||
* 入口参数:e - 事件指针 lv_event_t *
|
||||
* 返回值:无
|
||||
* 限定条件:容器已加入默认输入组并获焦
|
||||
* 函数说明:1. ↑/↓:列表页移选(首尾环绕,跨页连续),窗口随页切换后重绘;信息页不响应
|
||||
* 2. ESC/←:关闭页面返回菜单(导航状态未压层,原样还原)
|
||||
* 函数说明: 1. ESC/←:恒关页返回菜单(框架保证,页面钩子不可拦截)
|
||||
* 2. 其余键:key_cb 钩子先调(返回 true = 页已处理,框架跳过内置)
|
||||
* 3. 内置:↑/↓ 列表页移选(首尾环绕,跨页连续),窗口随页切换后重绘;
|
||||
* 信息页不响应;动态行数可能缩小,选中行越界时重置回首行
|
||||
*/
|
||||
static void cp_key_cb(lv_event_t *e) {
|
||||
const cp_def_t *d = &s_defs[s_open];
|
||||
const content_page_def_t *d = s_defs[s_open];
|
||||
lv_key_t key = (lv_key_t)lv_event_get_key(e);
|
||||
|
||||
/* ESC/←:关闭页面返回菜单屏(焦点/导航状态还原) */
|
||||
if (key == LV_KEY_ESC || key == LV_KEY_LEFT) {
|
||||
ui_content_page_close();
|
||||
return;
|
||||
}
|
||||
|
||||
/* 页面钩子先调:true = 页已处理,框架跳过内置语义 */
|
||||
if (d->key_cb != NULL && d->key_cb(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case LV_KEY_UP:
|
||||
if (d->selectable && d->total_rows > 0u) {
|
||||
case LV_KEY_UP: {
|
||||
uint16_t total = cp_row_total(d);
|
||||
|
||||
if (d->selectable != 0u && total > 0u) {
|
||||
if (s_sel >= total) {
|
||||
s_sel = 0u; /* 动态行数可能缩小:选中行越界重置回首行 */
|
||||
}
|
||||
/* 上移、首尾环绕:先加 total 再减 1 保证无符号下不为负 */
|
||||
s_sel = (uint16_t)((s_sel + d->total_rows - 1u) % d->total_rows);
|
||||
s_sel = (uint16_t)((s_sel + total - 1u) % total);
|
||||
lv_obj_invalidate(s_cont); /* 重绘(选中带/窗口/页码可能变化) */
|
||||
}
|
||||
break;
|
||||
case LV_KEY_DOWN:
|
||||
if (d->selectable && d->total_rows > 0u) {
|
||||
s_sel = (uint16_t)((s_sel + 1u) % d->total_rows); /* 下移、越尾绕回首行 */
|
||||
}
|
||||
case LV_KEY_DOWN: {
|
||||
uint16_t total = cp_row_total(d);
|
||||
|
||||
if (d->selectable != 0u && total > 0u) {
|
||||
if (s_sel >= total) {
|
||||
s_sel = 0u; /* 动态行数可能缩小:选中行越界重置回首行 */
|
||||
}
|
||||
s_sel = (uint16_t)((s_sel + 1u) % total); /* 下移、越尾绕回首行 */
|
||||
lv_obj_invalidate(s_cont);
|
||||
}
|
||||
break;
|
||||
case LV_KEY_ESC:
|
||||
case LV_KEY_LEFT:
|
||||
ui_content_page_close(); /* 返回菜单屏(焦点/导航状态还原) */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break; /* 其余键值忽略 */
|
||||
}
|
||||
@@ -411,7 +386,7 @@ static void cp_key_cb(lv_event_t *e) {
|
||||
/*
|
||||
* 函数功能:打开指定内容页(建屏 + 切屏 + 焦点置页面容器)
|
||||
* 入口参数:id - 内容页 ID content_page_id_t
|
||||
* 返回值:true - 成功;false - 失败(ID 无效/已有页面打开/对象创建失败)
|
||||
* 返回值:true - 成功;false - 失败(ID 无效/已有页面打开/无描述符/对象创建失败)
|
||||
* 限定条件:ui_menu_init() 已完成(默认输入组与菜单屏存在)
|
||||
* 函数说明:1. lv_obj_create(NULL) 新建独立屏幕 + 全屏容器(自绘载体,无子对象)
|
||||
* 2. 容器入默认输入组并获焦后再切屏——按键立即由本模块接管
|
||||
@@ -422,6 +397,12 @@ bool ui_content_page_open(content_page_id_t id) {
|
||||
return false; /* ID 无效或已有页面打开(防御) */
|
||||
}
|
||||
|
||||
const content_page_def_t *d = s_defs[id];
|
||||
if (d == NULL) {
|
||||
DBG_ERROR("page open: id=%u no descriptor (enum/table drift)", (unsigned)id);
|
||||
return false; /* 枚举/描述符表漂移:拒开并留痕,不崩溃 */
|
||||
}
|
||||
|
||||
s_scr = lv_obj_create(NULL); /* parent=NULL → 新建屏幕 */
|
||||
if (s_scr == NULL) {
|
||||
return false; /* LVGL 池耗尽 */
|
||||
@@ -451,7 +432,7 @@ bool ui_content_page_open(content_page_id_t id) {
|
||||
}
|
||||
|
||||
lv_screen_load(s_scr); /* 切到内容页(菜单屏对象保留、不销毁) */
|
||||
DBG_INFO("page open: id=%u rows=%u", (unsigned)id, (unsigned)s_defs[id].total_rows);
|
||||
DBG_INFO("page open: id=%u rows=%u", (unsigned)id, (unsigned)cp_row_total(d));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user