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.
This commit is contained in:
edisondeng
2026-07-31 19:14:14 +08:00
parent d4b89c9336
commit dac2ea4335
3 changed files with 59 additions and 34 deletions

View File

@@ -63,8 +63,8 @@ static void SetClockApp_onRun(void)
if (blink != time_edit_blink_on) if (blink != time_edit_blink_on)
{ {
time_edit_blink_on = blink; 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 { } else {
current_min = (current_min + 1) % 60; 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; return EVENT_HANDLED;
} }
if (evt->key_event == KEY_EVENT_DOWN_CLICK) if (evt->key_event == KEY_EVENT_DOWN_CLICK)
@@ -101,7 +102,8 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt)
} else { } else {
current_min = (current_min == 0) ? 59 : (current_min - 1); 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; return EVENT_HANDLED;
} }
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) if (evt->key_event == KEY_EVENT_CONFIRM_LONG)
@@ -112,7 +114,10 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt)
} else { } else {
time_edit_field = 1; 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; return EVENT_HANDLED;
} }
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) if (evt->key_event == KEY_EVENT_CONFIRM_CLICK)

View File

@@ -370,55 +370,68 @@ void UI_ShowMainMenu(u8 selected_index)
* @param selection 当前正在编辑聚焦的属性位 (1: 修改小时, 2: 修改分钟) * @param selection 当前正在编辑聚焦的属性位 (1: 修改小时, 2: 修改分钟)
* @param blink_on 当前 500ms 控制隐现的闪烁周期标志位 (1-绘制正常字0-以空格消隐该数值字符) * @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) void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on)
{ {
char time_str[6]; char time_str[6];
LCD_Clear(COLOR_BLACK); LCD_Clear(COLOR_BLACK);
// 绘制绿锁头等背景静态信息 // 绘制绿锁头等背景静态信息
LCD_DrawRectBorder(10, 23, 20, 15, COLOR_GREEN); LCD_DrawRectBorder(10, 23, 20, 15, COLOR_GREEN);
LCD_FillRect(15, 15, 2, 8, COLOR_GREEN); LCD_FillRect(15, 15, 2, 8, COLOR_GREEN);
LCD_FillRect(17, 15, 8, 2, COLOR_GREEN); LCD_FillRect(17, 15, 8, 2, COLOR_GREEN);
LCD_FillRect(25, 17, 2, 6, COLOR_GREEN); LCD_FillRect(25, 17, 2, 6, COLOR_GREEN);
// 移动电池百分比和图标到 135px 右上角 // 移动电池百分比和图标到 135px 右上角
LCD_ShowString(77, 24, "85%", COLOR_GRAY, COLOR_BLACK); LCD_ShowString(77, 24, "85%", COLOR_GRAY, COLOR_BLACK);
LCD_DrawMonoBitmap(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK); LCD_DrawMonoBitmap(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK);
// ====== 处理调节项一:小时的消隐/显示逻辑 ====== // 整页绘制时,小时/分钟数字一律完整显示 (消隐闪烁效果交给 UI_UpdateSetTimeDigit 局部刷新处理)
if (selection == 1 && !blink_on) time_str[0] = '0' + (hour / 10);
{ time_str[1] = '0' + (hour % 10);
// 聚焦在小时且处于灭周期,用空格隐藏数值,形成数值跳变闪烁调节感
time_str[0] = ' ';
time_str[1] = ' ';
}
else
{
time_str[0] = '0' + (hour / 10);
time_str[1] = '0' + (hour % 10);
}
time_str[2] = '\0'; 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) // 绘制中间冒号 (在 135px 下整体居中 X = 59)
LCD_ShowString16x32(59, 98, ":", COLOR_WHITE, COLOR_BLACK); LCD_ShowString16x32(59, 98, ":", COLOR_WHITE, COLOR_BLACK);
// ====== 处理调节项二:分钟的消隐/显示逻辑 ====== time_str[0] = '0' + (min / 10);
if (selection == 2 && !blink_on) time_str[1] = '0' + (min % 10);
{
// 聚焦在分钟且处于灭周期,用空格隐藏数值
time_str[0] = ' ';
time_str[1] = ' ';
}
else
{
time_str[0] = '0' + (min / 10);
time_str[1] = '0' + (min % 10);
}
time_str[2] = '\0'; 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(150, Lang_Get(STR_CLOCK_AMPM), COLOR_WHITE, COLOR_BLACK);
LCD_ShowStringCentered(195, Lang_Get(STR_CLOCK_DATE), COLOR_GRAY, 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);
}

View File

@@ -82,4 +82,11 @@ void UI_ShowMainMenu(u8 selected_index);
*/ */
void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on); 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__ #endif // __UI_H__