From dac2ea43351c3ae39abcfaee03b204cbaec69c05 Mon Sep 17 00:00:00 2001 From: edisondeng Date: Fri, 31 Jul 2026 19:14:14 +0800 Subject: [PATCH] fix(ui): partial-refresh time-set digit blink instead of full screen UI_ShowSetTimePage() cleared and redrew the entire screen on every 500ms blink toggle and on every up/down value change, causing a full-screen flash instead of just the intended hour/minute digit blinking. Split out UI_UpdateSetTimeDigit() which only repaints the 32x32px digit region for the field being edited; the full page draw is now only used on entry. Field-switch (long-press CONFIRM) refreshes both digit regions to clear any stale blanked-out state. --- App/app_set_clock.c | 15 ++++++---- App/ui.c | 71 +++++++++++++++++++++++++++------------------ App/ui.h | 7 +++++ 3 files changed, 59 insertions(+), 34 deletions(-) diff --git a/App/app_set_clock.c b/App/app_set_clock.c index b655314..e56cf53 100644 --- a/App/app_set_clock.c +++ b/App/app_set_clock.c @@ -63,8 +63,8 @@ static void SetClockApp_onRun(void) if (blink != time_edit_blink_on) { time_edit_blink_on = blink; - // 每次闪烁状态发生变化,重新刷写屏幕数值 - UI_ShowSetTimePage(current_hour, current_min, time_edit_field, time_edit_blink_on); + // 每次闪烁状态发生变化,只局部刷新正在调节的那个数字,不整屏重绘 + UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, time_edit_blink_on); } } @@ -90,7 +90,8 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt) } else { current_min = (current_min + 1) % 60; } - UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1); + time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期) + UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, 1); return EVENT_HANDLED; } if (evt->key_event == KEY_EVENT_DOWN_CLICK) @@ -101,7 +102,8 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt) } else { current_min = (current_min == 0) ? 59 : (current_min - 1); } - UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1); + time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期) + UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, 1); return EVENT_HANDLED; } if (evt->key_event == KEY_EVENT_CONFIRM_LONG) @@ -112,7 +114,10 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt) } else { time_edit_field = 1; } - UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1); + time_edit_blink_on = 1; // 切换焦点后两个字段都应处于可见状态 + // 两个数字区域都局部刷新一次,避免切换前正处于消隐周期的那个数字停留在涂黑状态 + UI_UpdateSetTimeDigit(current_hour, current_min, 1, 1); + UI_UpdateSetTimeDigit(current_hour, current_min, 2, 1); return EVENT_HANDLED; } if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) diff --git a/App/ui.c b/App/ui.c index f22ab6c..265b7f3 100644 --- a/App/ui.c +++ b/App/ui.c @@ -370,55 +370,68 @@ void UI_ShowMainMenu(u8 selected_index) * @param selection 当前正在编辑聚焦的属性位 (1: 修改小时, 2: 修改分钟) * @param blink_on 当前 500ms 控制隐现的闪烁周期标志位 (1-绘制正常字,0-以空格消隐该数值字符) */ +// 小时/分钟数字在屏幕上的固定坐标 (16x32 字体,两位数字宽度为 32px) +#define SET_TIME_DIGIT_Y 100 +#define SET_TIME_DIGIT_W 32 +#define SET_TIME_DIGIT_H 32 +#define SET_TIME_HOUR_X 23 +#define SET_TIME_MIN_X 75 + void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on) { char time_str[6]; LCD_Clear(COLOR_BLACK); - + // 绘制绿锁头等背景静态信息 LCD_DrawRectBorder(10, 23, 20, 15, COLOR_GREEN); LCD_FillRect(15, 15, 2, 8, COLOR_GREEN); LCD_FillRect(17, 15, 8, 2, COLOR_GREEN); LCD_FillRect(25, 17, 2, 6, COLOR_GREEN); - + // 移动电池百分比和图标到 135px 右上角 LCD_ShowString(77, 24, "85%", COLOR_GRAY, COLOR_BLACK); LCD_DrawMonoBitmap(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK); - // ====== 处理调节项一:小时的消隐/显示逻辑 ====== - if (selection == 1 && !blink_on) - { - // 聚焦在小时且处于灭周期,用空格隐藏数值,形成数值跳变闪烁调节感 - time_str[0] = ' '; - time_str[1] = ' '; - } - else - { - time_str[0] = '0' + (hour / 10); - time_str[1] = '0' + (hour % 10); - } + // 整页绘制时,小时/分钟数字一律完整显示 (消隐闪烁效果交给 UI_UpdateSetTimeDigit 局部刷新处理) + time_str[0] = '0' + (hour / 10); + time_str[1] = '0' + (hour % 10); time_str[2] = '\0'; - LCD_ShowString16x32(23, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘小时 (在 135px 下整体居中 X = 23) + LCD_ShowString16x32(SET_TIME_HOUR_X, SET_TIME_DIGIT_Y, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘小时 (在 135px 下整体居中 X = 23) // 绘制中间冒号 (在 135px 下整体居中 X = 59) LCD_ShowString16x32(59, 98, ":", COLOR_WHITE, COLOR_BLACK); - // ====== 处理调节项二:分钟的消隐/显示逻辑 ====== - if (selection == 2 && !blink_on) - { - // 聚焦在分钟且处于灭周期,用空格隐藏数值 - time_str[0] = ' '; - time_str[1] = ' '; - } - else - { - time_str[0] = '0' + (min / 10); - time_str[1] = '0' + (min % 10); - } + time_str[0] = '0' + (min / 10); + time_str[1] = '0' + (min % 10); time_str[2] = '\0'; - LCD_ShowString16x32(75, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘分钟 (在 135px 下整体居中 X = 75) - + LCD_ShowString16x32(SET_TIME_MIN_X, SET_TIME_DIGIT_Y, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘分钟 (在 135px 下整体居中 X = 75) + // 补齐底部的固定辅助元素 LCD_ShowStringCentered(150, Lang_Get(STR_CLOCK_AMPM), COLOR_WHITE, COLOR_BLACK); LCD_ShowStringCentered(195, Lang_Get(STR_CLOCK_DATE), COLOR_GRAY, COLOR_BLACK); } + +/** + * @brief 局部刷新时间设置界面里"正在调节的那一个"数字 (小时或分钟) + * @param selection 1:刷新小时区域, 2:刷新分钟区域 + * @param blink_on 1:显示数值, 0:消隐(涂黑),用于 500ms 周期闪烁效果 + * @details 只重画 32x32px 的数字区域,不触碰锁头/电池/冒号/AM-PM/日期等其它内容, + * 避免每次闪烁或调值都整屏 LCD_Clear() 造成全屏闪烁。 + */ +void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 selection, u8 blink_on) +{ + char time_str[3]; + u16 x = (selection == 1) ? SET_TIME_HOUR_X : SET_TIME_MIN_X; + u8 value = (selection == 1) ? hour : min; + + if (!blink_on) { + // 灭周期:直接把这一小块涂黑,形成消隐效果 + LCD_FillRect(x, SET_TIME_DIGIT_Y, SET_TIME_DIGIT_W, SET_TIME_DIGIT_H, COLOR_BLACK); + return; + } + + time_str[0] = '0' + (value / 10); + time_str[1] = '0' + (value % 10); + time_str[2] = '\0'; + LCD_ShowString16x32(x, SET_TIME_DIGIT_Y, time_str, COLOR_CYAN, COLOR_BLACK); +} diff --git a/App/ui.h b/App/ui.h index a6e31b5..96f8aeb 100644 --- a/App/ui.h +++ b/App/ui.h @@ -82,4 +82,11 @@ void UI_ShowMainMenu(u8 selected_index); */ void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on); +/** + * @brief 局部刷新时间设置界面里正在调节的那一个数字 (小时或分钟),用于闪烁/调值时避免整屏重绘 + * @param selection 1:刷新小时区域, 2:刷新分钟区域 + * @param blink_on 1:显示数值, 0:消隐(涂黑) + */ +void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 selection, u8 blink_on); + #endif // __UI_H__