sdk: sb_icons 扩充动作图标 + TopAppBar 位图图标支持
TopAppBar 动作项此前用字体码点(⚙↻⌕)绘制,4k 字库无这些码点→豆腐。改走位图: - sb_icons.h 追加 15 个 Material Symbols Rounded 动作位图(settings/refresh/search/ play_arrow/pause/skip_next/skip_previous/arrow_back/close/add/check/lyrics/ queue_music/download/heart),FILL=1 实心与状态栏一致;sb_icons[] 只追加(0-14 不变), 动作索引 15-29。 - 生成脚本 tools/gen_action_icons.py(cairosvg svg→32x32 单通道 alpha,SVG 缓存 icons_src/ 可复现、断网可跑)。 - meow_ui_gfx.c 抽取图标 blit 像素核心 icon_blit_px,新增 meow_gfx_blit_icon_ink (控件路径不标顶栏脏区);meow_gfx_blit_icon 状态栏路径行为不变。 - meow_ui_widget.c W_TOPAPPBAR 项支持位图模式:新 API meow_topappbar_set_item_icon (w, idx, icon_idx),绘制取主题 onSurface/按压向栏底色淡 12%,文本项行为不变; hit 用统一项宽。 - 公共头 widgets.h 加 MEOW_ICON_*(15-29) 枚举与 set_item_icon 声明;internal.h 声明 meow_gfx_blit_icon_ink。 - 宿主测试(test_meow_ui_widgets)加 topbar 位图图标绘制/命中/按压变淡 + 状态栏 blit 回归断言;test_umbrella 加 MEOW_ICON_* 编译期锁;MEOW_APP_SDK.md 补说明+索引表。 - 验证:宿主测试 ALL PASS(14项);交叉 zig 构建 0 warning;meow_ui.a 新 md5 1d69cdae55ab5dde3a98f5e2124f3656。
This commit is contained in:
1 parent
41427fdcb3
commit
3611cbbbde
24 files changed
+1006
-22
No files matched your search
@@ -23,6 +23,12 @@ enum { W_BTN = 0, W_SLIDER = 1, W_SWITCH = 2, W_LIST = 3,
|
||||
/* 容器(TopAppBar 动作 / NavigationBar 项 / TabBar 页签)子项上限。 */
|
||||
#define MEOW_CONTAINER_MAX 8
|
||||
|
||||
/* TopAppBar 位图动作图标(Material Symbols Rounded 单通道 alpha,见 sb_icons.h):
|
||||
* 动作单元格宽(32px 图标槽水平居中 + 两侧留白 8px)与目标 ink 高(MD3 24dp 图标)。
|
||||
* ink 垂直中线取栏中点(mid),与状态栏 28px 栏「文字中线」风格一致。 */
|
||||
#define MEOW_TOPBAR_ACTION_W 48
|
||||
#define MEOW_TOPBAR_ICON_INK 24
|
||||
|
||||
/* 按钮「按住」判定阈值:视觉上区分「短按按下」与「按住」(更深状态层)。
|
||||
* 阈值取 meow_ui_long_press_ms()(§6.3 通用长按默认 500ms,App 可配)——与长按事件同源,
|
||||
* 避免「长按已触发但视觉未加深」的不一致。触发语义不变(on_tap 仍按抬手判定)。 */
|
||||
@@ -79,6 +85,9 @@ struct meow_widget {
|
||||
char items[MEOW_CONTAINER_MAX][24]; /* W_TOPAPPBAR 动作 / W_NAVBAR 项 / W_TABBAR 页签 */
|
||||
int nitems; /* 上述项数 */
|
||||
int selected; /* W_NAVBAR / W_TABBAR 选中下标 */
|
||||
/* W_TOPAPPBAR 动作位图图标:每项 sb_icons[] 索引(≥0=画该图标;-1=画 items[i] 文本)。
|
||||
* 追加字段(calloc 归零为 0,故 create/add_action 显式置 -1 保证文本默认)。 */
|
||||
int item_icon[MEOW_CONTAINER_MAX];
|
||||
/* M2.71-bug8:W_LIST 行点击回调(可选)。 */
|
||||
meow_list_tap_fn tap_cb; /* 命中行回调(可 NULL) */
|
||||
void *tap_ctx; /* 回调 ctx */
|
||||
@@ -124,6 +133,22 @@ static int widget_disabled(const meow_widget *w) { return !(w->state & MEOW_WS_E
|
||||
static uint32_t state_tint(uint32_t base, const meow_theme *th, int t)
|
||||
{ return blend_color(base, th->onSurface, t); }
|
||||
|
||||
/* ---- TopAppBar 位图动作图标辅助(绘制与命中共用的「项宽」/「按压淡色」)----
|
||||
* 项宽:位图图标用固定单元格 MEOW_TOPBAR_ACTION_W(图标槽在该格内居中);文本项沿用
|
||||
* 原「文本宽 + 12」不等式(行为不变)。命中与绘制同源,避免 icon/text 混合排布错位。 */
|
||||
static int topbar_item_w(const meow_widget *w, const meow_theme *th, int i)
|
||||
{
|
||||
if (w->item_icon[i] >= 0) return MEOW_TOPBAR_ACTION_W;
|
||||
return meow_ui_text_width(w->items[i], th->font_body) + 12;
|
||||
}
|
||||
/* 动作颜色:默认 onSurface;按压态向栏底色(surfaceContainerHigh)淡 12%(§5.8.4 状态层)。 */
|
||||
static uint32_t topbar_action_color(const meow_widget *w, const meow_theme *th)
|
||||
{
|
||||
uint32_t col = th->onSurface;
|
||||
if (w->state & MEOW_WS_PRESSED) col = blend_color(col, th->surfaceContainerHigh, 12);
|
||||
return col;
|
||||
}
|
||||
|
||||
/* ---- §5.8.2/§5.8.3 公共 API:Options + 状态机 ---- */
|
||||
int meow_widget_set_opts(meow_widget *w, const meow_widget_opts *opts)
|
||||
{
|
||||
@@ -715,6 +740,7 @@ meow_widget *meow_topappbar_create(int x, int y, int w, int h, const char *title
|
||||
t->owner = meow_ui_activity_active();
|
||||
t->state = MEOW_WS_ENABLED;
|
||||
t->back_on = 0; t->nitems = 0;
|
||||
for (int i = 0; i < MEOW_CONTAINER_MAX; i++) t->item_icon[i] = -1; /* 默认文本项 */
|
||||
if (title) { strncpy(t->label, title, sizeof t->label - 1); t->label[sizeof t->label - 1] = 0; }
|
||||
meow_draw_widget_register(t);
|
||||
return t;
|
||||
@@ -737,10 +763,24 @@ int meow_topappbar_add_action(meow_widget *w, const char *label)
|
||||
if (label) strncpy(w->items[w->nitems], label, 23);
|
||||
w->items[w->nitems][23] = 0;
|
||||
int idx = w->nitems;
|
||||
w->item_icon[idx] = -1; /* 文本项(后续可用 set_item_icon 转位图) */
|
||||
w->nitems++;
|
||||
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
|
||||
return idx;
|
||||
}
|
||||
/* 把第 idx 个动作项设为位图图标(sb_icons[] 索引,MEOW_ICON_* 或 SB_I_*)。追加式 API:
|
||||
* 文本项(add_action 默认)行为不变;仅「设为图标后」该动作改用 meow_gfx_blit_icon_ink
|
||||
* 绘制(32px 槽居中 + ink 垂直对齐栏中点),颜色取主题 onSurface/按压态淡色。
|
||||
* 返回 0=成功;NULL/非 topbar/越界 idx/非法 icon_idx=负值。 */
|
||||
int meow_topappbar_set_item_icon(meow_widget *w, int idx, int icon_idx)
|
||||
{
|
||||
if (!w || w->type != W_TOPAPPBAR) return -1;
|
||||
if (idx < 0 || idx >= w->nitems) return -1;
|
||||
if (icon_idx < 0) return -1; /* ≥0 的顶层校验;越界索引由 blit 内部 clamp 兜底 */
|
||||
w->item_icon[idx] = icon_idx;
|
||||
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
|
||||
return 0;
|
||||
}
|
||||
int meow_topappbar_hit(meow_widget *w, int x, int y)
|
||||
{
|
||||
if (!w || w->type != W_TOPAPPBAR) return -1;
|
||||
@@ -749,7 +789,7 @@ int meow_topappbar_hit(meow_widget *w, int x, int y)
|
||||
const meow_theme *th = meow_theme_get();
|
||||
int ax = w->x + w->w - 10;
|
||||
for (int i = w->nitems - 1; i >= 0; i--) {
|
||||
int aw = meow_ui_text_width(w->items[i], th->font_body) + 12;
|
||||
int aw = topbar_item_w(w, th, i); /* 位图图标用固定单元格;文本项用原不等式 */
|
||||
ax -= aw;
|
||||
if (x >= ax && x < ax + aw && x >= w->x + 100) return i; /* 不压标题区/返回区 */
|
||||
}
|
||||
@@ -1849,12 +1889,21 @@ void meow_widget_draw(meow_widget *w)
|
||||
tx = w->x + 48;
|
||||
}
|
||||
if (w->label[0]) meow_ui_text(tx, ty, w->label, th->font_title, th->onSurface);
|
||||
/* 动作区:从右往左排。位图图标(item_icon>=0)用 sb_icons[] 位图(Material Symbols
|
||||
* Rounded)经 meow_gfx_blit_icon_ink 画(32px 槽在动作格内水平居中 + ink 垂直对齐 mid,
|
||||
* 颜色 = onSurface/按压淡色);文本项沿用 meow_ui_text_center(行为不变)。 */
|
||||
int ay = mid - meow_ui_text_height(th->font_body) / 2;
|
||||
uint32_t acol = topbar_action_color(w, th);
|
||||
int ax = w->x + w->w - 12;
|
||||
for (int i = w->nitems - 1; i >= 0; i--) {
|
||||
int aw = meow_ui_text_width(w->items[i], th->font_body) + 12;
|
||||
int aw = topbar_item_w(w, th, i);
|
||||
ax -= aw;
|
||||
meow_ui_text_center(ax + aw / 2, ay, w->items[i], th->font_body, th->onSurface);
|
||||
if (w->item_icon[i] >= 0) {
|
||||
int slot_x = ax + (aw - MEOW_SB_ICON_SIZE) / 2; /* 32px 槽在格内居中 */
|
||||
meow_gfx_blit_icon_ink(w->item_icon[i], slot_x, MEOW_TOPBAR_ICON_INK, acol, mid);
|
||||
} else {
|
||||
meow_ui_text_center(ax + aw / 2, ay, w->items[i], th->font_body, acol);
|
||||
}
|
||||
}
|
||||
meow_ui_fill_rect(w->x, w->y + w->h - 1, w->w, 1, th->outlineVariant);
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user