Fix mode-select UX and status-bar battery alignment.

Single-tap mode entry, hide top separator and row artifact line, center battery with vol/BT, and make % match digit height.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-06 18:19:47 +08:00
parent 49af730f91
commit 5daf5e794b
4 changed files with 58 additions and 67 deletions

View File

@ -19,9 +19,6 @@ void RGB_Y_TO_G()
#define UI_MODE_SCREEN_WIDTH 240
#define UI_MODE_SCREEN_HEIGHT 320
/* 模式选择页焦点0=万能 1=普通 2=专业,默认选中万能(与规范一致) */
static uint8_t s_mode_select_focus = 0;
extern bool InModeFlag;
/* 0902/0819三行模式撑满状态栏下方至底边无底栏222x88 @ y=43/135/225 */
@ -31,44 +28,28 @@ extern bool InModeFlag;
#define UI0902_MODE_ROW_Y0 43
#define UI0902_MODE_ROW_DY 92
static const uint32_t s_mode_row_addr[3][2] = {
{ UI0902_ROW_UNIVERSAL_NOT_ADDR, UI0902_ROW_UNIVERSAL_SEL_ADDR }, /* 0 万能 */
{ UI0902_ROW_NORMAL_NOT_ADDR, UI0902_ROW_NORMAL_SEL_ADDR }, /* 1 普通 */
{ UI0902_ROW_EXPERT_NOT_ADDR, UI0902_ROW_EXPERT_SEL_ADDR }, /* 2 专业 */
/* 模式页不显示焦点:三行均用未选中资源;单击直接进入 */
static const uint32_t s_mode_row_addr[3] = {
UI0902_ROW_UNIVERSAL_NOT_ADDR, /* 0 万能 */
UI0902_ROW_NORMAL_NOT_ADDR, /* 1 普通 */
UI0902_ROW_EXPERT_NOT_ADDR, /* 2 专业 */
};
static void UI_DrawModeSelectButton(uint16_t y, uint8_t idx, uint8_t focused)
{
LCD_WR_PIC_FROM_FLASH(UI0902_MODE_ROW_X, y, UI0902_MODE_ROW_W, UI0902_MODE_ROW_H,
s_mode_row_addr[idx][focused ? 1 : 0]);
}
static void UI_ModeSelect_DrawButtonAt(uint8_t idx)
{
if (idx > 2)
return;
UI_DrawModeSelectButton((uint16_t)(UI0902_MODE_ROW_Y0 + idx * UI0902_MODE_ROW_DY),
idx, s_mode_select_focus == idx);
}
static void UI_ModeSelect_SetFocus(uint8_t idx)
{
uint8_t prev;
if (idx > 2 || idx == s_mode_select_focus)
return;
prev = s_mode_select_focus;
s_mode_select_focus = idx;
/* 只重绘新旧两个按钮,避免整页三键闪烁 */
UI_ModeSelect_DrawButtonAt(prev);
UI_ModeSelect_DrawButtonAt(idx);
}
static void UI_ModeSelect_DrawButtons(void)
{
UI_ModeSelect_DrawButtonAt(0);
UI_ModeSelect_DrawButtonAt(1);
UI_ModeSelect_DrawButtonAt(2);
uint8_t i;
for (i = 0; i < 3; i++) {
uint16_t y = (uint16_t)(UI0902_MODE_ROW_Y0 + i * UI0902_MODE_ROW_DY);
LCD_WR_PIC_FROM_FLASH(UI0902_MODE_ROW_X, y,
UI0902_MODE_ROW_W, UI0902_MODE_ROW_H,
s_mode_row_addr[i]);
/* 万能模式素材顶部有残留近白横线(相对行内 y=7/8盖成行底色 */
if (i == 0) {
LCD_FillByColor(UI0902_MODE_ROW_X, (uint16_t)(y + 7),
(uint16_t)(UI0902_MODE_ROW_X + UI0902_MODE_ROW_W),
(uint16_t)(y + 9), UI0902_ROW_BG);
}
}
}
void UI_ReturnToModeSelect(void)
@ -76,7 +57,6 @@ void UI_ReturnToModeSelect(void)
StartFlag = 0;
InModeFlag = false;
AutoBandTop1_Stop();
s_mode_select_focus = 0;
CallUI_Idle();
UI_DrawModeSelectScreen();
}
@ -93,10 +73,10 @@ void UI_DrawModeSelectScreen(void)
}
const Touch_AreaTypeDef Touch_ModeSelect_Areas[] = {
/* Flag=按钮序号(0万能/1普通/2专业)ID=进入 TAB。三行撑满,无底栏 */
{ 9, 231, 43, 130, 0, 0, 0, NULL },
{ 9, 231, 135, 222, 1, 0, 2, NULL },
{ 9, 231, 225, 312, 2, 0, 1, NULL },
/* Flag=按钮序号(0万能/1普通/2专业)ID=进入 TAB。全宽便于命中 */
{ 0, 239, 43, 130, 0, 0, 0, NULL },
{ 0, 239, 135, 222, 1, 0, 2, NULL },
{ 0, 239, 225, 312, 2, 0, 1, NULL },
};
#define TOUCH_AREA_MODE_SELECT_NUM (sizeof(Touch_ModeSelect_Areas)/sizeof(Touch_AreaTypeDef))
@ -140,8 +120,8 @@ void LoadConfig(void)
void Touch_Mode_Select_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex)
{
(void)areaIndex;
(void)FLAG;
StartTask();
s_mode_select_focus = (uint8_t)FLAG;
/* ID 为 TAB 索引0=万能(Song) 1=专业(Expert) 2=普通(Free) */
mGuiData[GUI_TAB_INDEX].Current = ID;
InModeFlag = true;
@ -184,7 +164,6 @@ void IdleProcess(DisplayTaskMessage_Type msg)
app_adc_sync_volume(vol);
Send_volume(vol);
s_mode_select_focus = 0;
UI_DrawModeSelectScreen();
TM1629D_AllLedOn(LED_COLOR_G);
TM1629D_UpdateDisplay(0);
@ -221,20 +200,16 @@ void IdleProcess(DisplayTaskMessage_Type msg)
msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max )
{
hit = 1U;
uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag;
LOG_I("UI", "mode_select hit area=%u row=%u focus=%u x=%u y=%u",
(unsigned)k, (unsigned)row, (unsigned)s_mode_select_focus,
LOG_I("UI", "mode_select hit area=%u row=%u x=%u y=%u",
(unsigned)k,
(unsigned)Touch_ModeSelect_Areas[k].Flag,
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
/* 已聚焦 → 进入;未聚焦 → 切蓝焦点,再点一次进入 */
if (row == s_mode_select_focus) {
if (now - s_last_enter_ms < 300U)
break;
s_last_enter_ms = now;
Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag,
Touch_ModeSelect_Areas[k].ID, k);
} else {
UI_ModeSelect_SetFocus(row);
}
/* 单击直接进入对应模式主页 */
if (now - s_last_enter_ms < 300U)
break;
s_last_enter_ms = now;
Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag,
Touch_ModeSelect_Areas[k].ID, k);
break;
}
}

View File

@ -226,13 +226,17 @@ uint8_t UI_SetFocus(uint8_t widget_id)
return 1;
}
void UI_DrawStatusSepLine(void)
{
/* 模式选择等页不需要顶栏底部分割线,保留空实现以免局部刷新再画出 */
(void)0;
}
void label_top()
{
const uint16_t btn_color = /*DARKLGRAY*/0x2988;
LCD_FillByColor(0, 0, 240, UI_STATUS_BAR_H, UI0902_BG_COLOR);
/* 音量条:渐变 + 圆角(见 Draw_Volume_Bar */
Draw_Volume_Bar(UI0902_VOL_X, UI0902_VOL_Y, level, 1, WHITE, GRAY);
LCD_DrawLine(0, 26, 240, 26, btn_color);
Show_BL_Icon(mGuiData[GUI_BL_SW].Current);
Show_Battery_Icon(usb_charging_state);
}
@ -297,15 +301,22 @@ void UI_GotoCurrentModePage(void)
/* 蓝牙图标:设计稿居中 */
void Show_BL_Icon(uint8_t value)
{
static int8_t s_bt_pwr = -1;
/* Fill 终点为开区间,传 W/H 本身;高度须停在分割线之上 */
LCD_FillByColor(UI0902_BT_X, UI0902_BT_Y,
UI0902_BT_X + UI0902_BT_W - 1,
UI0902_BT_Y + UI0902_BT_H - 1, UI0902_BG_COLOR);
UI0902_BT_X + UI0902_BT_W,
UI0902_BT_Y + UI0902_BT_H, UI0902_BG_COLOR);
if (value)
{
LCD_WR_PIC_Trans(UI0902_BT_X, UI0902_BT_Y, UI0902_BT_W, UI0902_BT_H,
gImage_UI0902_Bluetooth_11x17, BLACK);
}
BSP_BlueToothPowerEnable(value);
if (s_bt_pwr != (int8_t)value)
{
s_bt_pwr = (int8_t)value;
BSP_BlueToothPowerEnable(value);
}
}
void Draw_Status_Battery_Icon(uint8_t battery_percent)
@ -337,7 +348,8 @@ void Draw_Status_Battery_Icon(uint8_t battery_percent)
if ((int16_t)text_y < 0)
text_y = 0;
LCD_FillByColor(bat_x > 2 ? (uint16_t)(bat_x - 2) : 0, 0, 240, UI_STATUS_BAR_H,
/* 只清分割线上方 */
LCD_FillByColor(bat_x > 2 ? (uint16_t)(bat_x - 2) : 0, 0, 240, UI0902_STATUS_SEP_Y,
UI0902_BG_COLOR);
/* 实心电量条:内腔约 x+3..x+23宽21勿盖住右侧壳壁 */
@ -345,8 +357,8 @@ void Draw_Status_Battery_Icon(uint8_t battery_percent)
if (fill_w > 0) {
fill_x1 = (uint16_t)(bat_x + 3);
fill_y1 = (uint16_t)(UI0902_BATTERY_Y + 2);
fill_x2 = (uint16_t)(fill_x1 + fill_w - 1);
fill_y2 = (uint16_t)(fill_y1 + 7);
fill_x2 = (uint16_t)(fill_x1 + fill_w);
fill_y2 = (uint16_t)(fill_y1 + 8);
LCD_FillByColor(fill_x1, fill_y1, fill_x2, fill_y2, WHITE);
}
LCD_WR_PIC_Trans(bat_x, UI0902_BATTERY_Y, UI0902_BATTERY_W, UI0902_BATTERY_H,

View File

@ -28,6 +28,8 @@ void CallUI_RestoreSelect(void);
#define UI_STATUS_BAR_H 26
#define UI0902_STATUS_SEP_Y 26
#define UI0902_STATUS_SEP_COLOR 0x52AA /* 比旧 0x2988 更清晰,避免在蓝牙下看成断开 */
/* 0902 设计稿配色与底栏导航 */
#define UI0902_BG_COLOR 0x0042 /* #000813 页面背景 */
#define UI0902_ROW_BG 0x2147 /* #242B3A 列表行背景 */
@ -122,7 +124,8 @@ void CallUI_RestoreSelect(void);
#define UI0902_BT_Y 5
#define UI0902_BATTERY_W 29
#define UI0902_BATTERY_H 12
#define UI0902_BATTERY_Y 13 /* 顶≈y13底 y24与分隔线 y26 留空,避免底边被切 */
/* 与音量(y3..20)/蓝牙(y5..21)视觉中心对齐12px 高 → 顶 y7 */
#define UI0902_BATTERY_Y 7
#define UI0902_BATTERY_RIGHT_MARGIN 6
#define UI0902_BATTERY_TEXT_GAP 4
#define UI0902_BATTERY_TEXT_SIZE 9 /* mode.png 百分比字号 ≈9完整显示 % */
@ -191,6 +194,7 @@ void UI_GetFocusGrad(uint8_t widget_id, uint16_t *c_top, uint16_t *c_bot);
void Draw_Status_Battery_Icon(uint8_t battery_percent);
void Show_Battery_Icon(uint8_t flag);
void UI_DrawStatusSepLine(void);
void Show_BL_Icon(uint8_t value);
void Draw_Tab_Section_Menu(const LEBEL_UI *UI, TAB_SECTION_INDEX select_tab);

View File

@ -997,7 +997,7 @@ const unsigned char ascii_94[][9]={
{0x00,0x00,0x00,0x14,0x14,0x14,0x00,0x00,0x00},/*""",2*/
{0x24,0x24,0x7E,0x24,0x24,0x12,0x7F,0x12,0x12},/*"#",3*/
{0x0C,0x0C,0x02,0x02,0x0C,0x10,0x10,0x0C,0x0C},/*"$",4*/
{0x02,0x25,0x12,0x08,0x24,0x52,0x20,0x00,0x00},/*"%",5*/
{0x26,0x29,0x29,0x16,0x08,0x34,0x4A,0x4A,0x34},/*"%",5*/ /* 9px 满高,与数字同高 */
{0x0C,0x12,0x12,0x0A,0x26,0x25,0x19,0x09,0x36},/*"&",6*/
{0x00,0x00,0x00,0x08,0x08,0x08,0x00,0x00,0x00},/*"'",7*/
{0x08,0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x08},/*"(",8*/