style(md3): 全面MD3对齐P0-P3 — P0扁平行列表容器化(meow_listview_set_container容器模式:surfaceContainer圆角卡12dp+tonal状态层+去分隔线;sub_page/settings_page/bg_page圆角容器) P1按钮胶囊化+shape令牌(extrasmall/small/medium/large/full) P2状态层补齐 P3子控件(Switch off-track/NavBar pill64×32/Checkbox24/对话框28);宿主test_meow_md3等全过,0warning;meow_ui.a变M6.36需重编+四App重链
This commit is contained in:
1 parent
3fea237306
commit
b712088daa
6 files changed
+343
-75
No files matched your search
@@ -226,9 +226,9 @@ static void bgm_row_draw(void *ctx, int idx, sub_row_t *r,
|
||||
int ry = cy + (ch - (th + tsub + 4)) / 2; /* 内容在卡内垂直居中(行中心=卡中心) */
|
||||
if (r->label) meow_ui_text(rx, ry, r->label, 20, mt->onSurface);
|
||||
if (r->sub) meow_ui_text(rx, ry + th + 4, r->sub, 16, mt->onSurfaceVariant);
|
||||
/* 行内杀按钮(圆角框 + 「杀」;error=红=杀) */
|
||||
/* 行内杀按钮(全形=胶囊(bh/2);「杀」;error=红=杀)——P1 按钮胶囊化 */
|
||||
int bx, by, bw, bh; bgm_btn_rect(x, y, w, h, &bx, &by, &bw, &bh);
|
||||
meow_ui_draw_rect_round(bx, by, bw, bh, 10, mt->error);
|
||||
meow_ui_draw_rect_round(bx, by, bw, bh, bh / 2, mt->error);
|
||||
int bth = meow_ui_text_height(16);
|
||||
if (bth > bh) bth = bh;
|
||||
meow_ui_text_center(bx + bw / 2, by + (bh - bth) / 2, "杀", 16, mt->error);
|
||||
|
||||
@@ -780,8 +780,8 @@ static void dd_modal_paint(const meow_ui_theme_t *th, int W, int H, int d_x, int
|
||||
int content_top, int content_bot, int dd_scroll)
|
||||
{
|
||||
meow_ui_fill_rect_alpha(0, 0, W, H, 0x000000, 150);
|
||||
meow_gfx_fill_round(d_x, d_y, d_w, d_h, 16, th->surface_container);
|
||||
meow_ui_draw_rect_round(d_x, d_y, d_w, d_h, 16, th->outline);
|
||||
meow_gfx_fill_round(d_x, d_y, d_w, d_h, 28, th->surface_container); /* MD3 extraLarge 28(原 16 偏小) */
|
||||
meow_ui_draw_rect_round(d_x, d_y, d_w, d_h, 28, th->outline);
|
||||
if (mfont_ready) ui_draw(d_x + 18, d_y + 8, title, th->on_surface, 20);
|
||||
else draw_text(d_x + 18, d_y + 8, title, 2, th->on_surface);
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -1094,6 +1094,11 @@ static int s_font_dropdown(const srow_t *r, char *out_val, int vlen)
|
||||
#define SET_TRACK_CY 48 /* 滑条 track 中心相对行顶 y(=SET_SLIDER_YOFF+3,与绘制对齐) */
|
||||
#define SET_SLIDER_LY 12 /* 滑条行 label 顶相对行顶 y(上移给 track 留位) */
|
||||
#define SET_SWITCH_POOL 12
|
||||
/* MD3 容器化(P0):设置页行=surface 上 surfaceContainer 圆角卡 + 行间空隙(去分隔线);
|
||||
* 卡横向外边距=SET_CARD_X(8),卡在行高内上下对称内缩(行中心=卡中心,同主界面/ncm 歌单手法)。 */
|
||||
#define SET_ROW_CARD_X SET_CARD_X /* 8:卡左缘 = 内容区左缘 */
|
||||
#define SET_ROW_CARD_G 8 /* 卡纵向间隙(px) */
|
||||
#define SET_ROW_CARD_R 12 /* 卡圆角(12dp) */
|
||||
|
||||
static meow_widget *g_set_lv = NULL; /* meow_listview(虚拟化) */
|
||||
static meow_scroll *g_set_sc = NULL; /* 滚动物理 */
|
||||
@@ -1155,24 +1160,30 @@ static void set_lv_draw(int idx, int x, int y, int w, int h, int state, void *ct
|
||||
uint32_t textcol = sel ? mt->onPrimaryContainer : mt->onSurface;
|
||||
uint32_t subcol = sel ? mt->onPrimaryContainer : mt->onSurfaceVariant;
|
||||
|
||||
/* MD3 容器化(P0):行=surface 上 surfaceContainer 圆角卡;段头=surface 上的 primary 段标签(无卡)。 */
|
||||
int cx = x + SET_ROW_CARD_X; /* 卡左缘 */
|
||||
int cw = w - 2 * SET_ROW_CARD_X; /* 卡宽 */
|
||||
int cy = y + SET_ROW_CARD_G / 2; /* 卡顶(行内对称内缩) */
|
||||
int ch = SET_ITEM_H - SET_ROW_CARD_G; /* 卡高 */
|
||||
|
||||
if (r->ctrl == SC_HEADER) {
|
||||
meow_ui_fill_rect(x, y, w, SET_ITEM_H, mt->surfaceContainerHigh);
|
||||
int ty = y + (SET_ITEM_H - thh) / 2;
|
||||
if (ty >= 0) meow_ui_text(x + 16, ty, s_row_label(r), mt->font_body, mt->primary);
|
||||
meow_ui_fill_rect(x, y + SET_ITEM_H - 1, w, 1, mt->outlineVariant);
|
||||
if (ty >= 0) meow_ui_text(cx + 16, ty, s_row_label(r), mt->font_body, mt->primary);
|
||||
return;
|
||||
}
|
||||
if (sel) meow_ui_fill_rect(x, y, w, SET_ITEM_H, mt->primaryContainer);
|
||||
else if (press) meow_ui_fill_rect_alpha(x, y, w, SET_ITEM_H, mt->primary, 26);
|
||||
meow_gfx_fill_round(cx, cy, cw, ch, SET_ROW_CARD_R, mt->surfaceContainer);
|
||||
if (sel) meow_gfx_fill_round(cx, cy, cw, ch, SET_ROW_CARD_R, mt->primaryContainer);
|
||||
else if (press) meow_gfx_fill_round_alpha(cx, cy, cw, ch, SET_ROW_CARD_R, mt->primary, 26);
|
||||
|
||||
int ly = y + (SET_ITEM_H - thh) / 2; /* label 单行垂直居中 */
|
||||
int rgt = cx + cw - 16; /* 卡内右缘(内容右对齐锚点) */
|
||||
switch (r->ctrl) {
|
||||
case SC_SWITCH: {
|
||||
meow_ui_text(x + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
meow_ui_text(cx + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
meow_widget *sw = set_sw_take();
|
||||
if (sw) {
|
||||
int on = 0; meow_settings_get_switch(r->key, &on);
|
||||
meow_widget_set_rect(sw, x + w - 16 - 56, y + (SET_ITEM_H - 32) / 2, 56, 32);
|
||||
meow_widget_set_rect(sw, rgt - 56, y + (SET_ITEM_H - 32) / 2, 56, 32);
|
||||
meow_switch_set(sw, on);
|
||||
meow_widget_draw(sw);
|
||||
}
|
||||
@@ -1180,9 +1191,9 @@ static void set_lv_draw(int idx, int x, int y, int w, int h, int state, void *ct
|
||||
}
|
||||
case SC_SLIDER: {
|
||||
/* label 上移一行,track 放行下方(中心=SET_SLIDER_YOFF+3=48),与拖动命中带对齐 */
|
||||
meow_ui_text(x + 16, y + SET_SLIDER_LY, s_row_label(r), mt->font_body, textcol);
|
||||
meow_ui_text(cx + 16, y + SET_SLIDER_LY, s_row_label(r), mt->font_body, textcol);
|
||||
char vb[32]; s_fmt_value(r, vb, sizeof vb);
|
||||
meow_ui_text(x + w - 16 - meow_ui_text_width(vb, mt->font_body), y + SET_SLIDER_LY, vb, mt->font_body, subcol);
|
||||
meow_ui_text(rgt - meow_ui_text_width(vb, mt->font_body), y + SET_SLIDER_LY, vb, mt->font_body, subcol);
|
||||
int v = 0; meow_settings_get_int(r->key, &v);
|
||||
/* 息屏时间为档位索引型(秒→索引 等距画);其余 clamp 到 [min,max] */
|
||||
if (!strcmp(r->key, "display.screen_off_timeout")) v = s_time_tier_idx(v);
|
||||
@@ -1191,30 +1202,29 @@ static void set_lv_draw(int idx, int x, int y, int w, int h, int state, void *ct
|
||||
break;
|
||||
}
|
||||
case SC_INFO: {
|
||||
meow_ui_text(x + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
meow_ui_text(cx + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
char vb[48]; s_net_get(r, vb, sizeof vb);
|
||||
meow_ui_text(x + w - 16 - meow_ui_text_width(vb, mt->font_body), ly, vb, mt->font_body, subcol);
|
||||
meow_ui_text(rgt - meow_ui_text_width(vb, mt->font_body), ly, vb, mt->font_body, subcol);
|
||||
break;
|
||||
}
|
||||
case SC_LIST: {
|
||||
meow_ui_text(x + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
meow_ui_text(cx + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
char vb[48]; s_net_get(r, vb, sizeof vb);
|
||||
int vx = x + w - 16 - 12 - meow_ui_text_width(vb, mt->font_body);
|
||||
int vx = rgt - 12 - meow_ui_text_width(vb, mt->font_body);
|
||||
meow_ui_text(vx, ly, vb, mt->font_body, subcol);
|
||||
s_draw_chevron(x + w - 16, y + SET_ITEM_H / 2, subcol);
|
||||
s_draw_chevron(rgt, y + SET_ITEM_H / 2, subcol);
|
||||
break;
|
||||
}
|
||||
default: { /* SC_ENUM / SC_PRESET */
|
||||
meow_ui_text(x + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
meow_ui_text(cx + 16, ly, s_row_label(r), mt->font_body, textcol);
|
||||
char vb[40]; s_display_value(r, vb, sizeof vb);
|
||||
int vx = x + w - 16 - meow_ui_text_width(vb, mt->font_body);
|
||||
int vx = rgt - meow_ui_text_width(vb, mt->font_body);
|
||||
meow_ui_text(vx, ly, vb, mt->font_body, subcol);
|
||||
s_draw_chevron(vx - 8, y + SET_ITEM_H / 2, subcol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
meow_ui_fill_rect(x, y + SET_ITEM_H - 1, w, 1, mt->outlineVariant);
|
||||
if (dis) meow_ui_fill_rect_alpha(x, y, w, SET_ITEM_H, mt->onSurface, 90);
|
||||
if (dis) meow_gfx_fill_round_alpha(cx, cy, cw, ch, SET_ROW_CARD_R, mt->onSurface, 90);
|
||||
}
|
||||
|
||||
/* ---- meow_scroll 回调(包 listview)---- */
|
||||
@@ -1229,7 +1239,7 @@ static void set_redraw_region(void *ctx)
|
||||
int lvx, lvy, lvw, lvh; set_lv_rect(&lvx, &lvy, &lvw, &lvh);
|
||||
if (lvh <= 0) return;
|
||||
const meow_ui_theme_t *th = s_ui_theme();
|
||||
meow_ui_fill_rect(lvx, lvy, lvw, lvh, th->surface_variant);
|
||||
meow_ui_fill_rect(lvx, lvy, lvw, lvh, th->surface); /* P0:内容底改 surface(卡在其上抬升) */
|
||||
if (g_set_lv) { g_set_sw_use = 0; meow_widget_draw(g_set_lv); }
|
||||
meow_dirty_add(lvx, lvy, lvw, lvh);
|
||||
meow_ui_flush();
|
||||
@@ -1274,7 +1284,7 @@ static void set_paint_page(int sel)
|
||||
if (mfont_ready) ui_draw(24, 50, meow_str_zh("menu.settings", "系统设置"), th->on_surface, 28);
|
||||
else draw_text(24, 30, "SETTINGS", 3, th->on_surface);
|
||||
fill_rect(0, 50 + (mfont_ready ? meow_font_line_height(28) : 24) + 2, W, 2, th->outline);
|
||||
fill_rect(0, SET_CARD_Y, W, H - SET_CARD_Y, th->surface_variant);
|
||||
fill_rect(0, SET_CARD_Y, W, H - SET_CARD_Y, th->surface); /* P0:内容底 surface,行用圆角卡抬升 */
|
||||
if (g_set_lv) {
|
||||
g_set_sw_use = 0;
|
||||
int p = s_vis_of(sel); if (p >= 0) meow_listview_set_sel(g_set_lv, p);
|
||||
|
||||
@@ -619,7 +619,7 @@ static void sp_paint_top_action(void)
|
||||
if (w <= 0 || h <= 0) return;
|
||||
const meow_theme *mt = meow_theme_get();
|
||||
uint32_t col = mt->primary;
|
||||
meow_ui_draw_rect_round(x, y, w, h, 10, col); /* 圆角描边按钮 */
|
||||
meow_ui_draw_rect_round(x, y, w, h, h / 2, col); /* 全形=胶囊描边按钮(P1) */
|
||||
int th = meow_ui_text_height(20);
|
||||
if (th > h) th = h;
|
||||
meow_ui_text_center(x + w / 2, y + (h - th) / 2, g_sp->top_action, 20, col);
|
||||
@@ -658,6 +658,9 @@ static void sp_widgets_create(void)
|
||||
/* 双行富 item + 无左图标 + 右尾件(SWITCH/ARROW);行高 56 */
|
||||
meow_listview_set_item_renderer(g_lv, 2, 0, 1);
|
||||
meow_listview_set_item_h(g_lv, SUB_ITEM_H);
|
||||
/* MD3(P0):默认 renderer 容器模式——行=surfaceContainer 圆角卡+行间空隙,
|
||||
* 选中/按压 tonal(primaryContainer/primary α26)、去冗余分隔线;段头=surface 上的 primary 段标签。 */
|
||||
meow_listview_set_container(g_lv, 1);
|
||||
}
|
||||
/* 注:刻意不 set_snap —— SDK meow_scroll 的 snap 以「fling 起点」为吸附目标,快速滑动时会
|
||||
* 从自然停点往回拉一整行(实测 697→336),UX 不佳;默认 ease-out 惯性停(无 snap)更顺滑。
|
||||
|
||||
@@ -146,6 +146,16 @@ enum {
|
||||
meow_widget *meow_btn_create_variant(int x, int y, int w, int h, const char *label, int variant);
|
||||
int meow_btn_set_variant(meow_widget *w, int variant); /* 越界 clamp;0=成功 */
|
||||
|
||||
/* ---- MD3 shape 层级(§5.8.6,Material You 圆角体系,单位 px)----
|
||||
* 组件按角色落到四档 + 胶囊:按钮=full(全高一半)、卡=large(16)、输入框=small(8)、
|
||||
* 勾选=extrasmall(4)。theme.radius/radius_card 为风格族默认;App 可经 opts.radius 逐控件覆盖。
|
||||
* 全高一半用 MEOW_SHAPE_FULL(h) 宏(控件的胶囊圆角)。 */
|
||||
#define MEOW_SHAPE_EXTRASMALL 4 /* 勾选 Checkbox/Radio */
|
||||
#define MEOW_SHAPE_SMALL 8 /* 输入框 TextField */
|
||||
#define MEOW_SHAPE_MEDIUM 12 /* 主题默认 radius(列表卡/通用控件) */
|
||||
#define MEOW_SHAPE_LARGE 16 /* 卡片/容器(theme.radius_card 默认) */
|
||||
#define MEOW_SHAPE_FULL(h) ((h) / 2) /* 全形=胶囊(按钮/导航等) */
|
||||
|
||||
/* ---- TextField(单行文本输入,接 IME §5.1)---- */
|
||||
/* placeholder=提示文案;buf=App 持有的文本缓冲(组件不回拷,只绘制/编辑其上);maxlen=含 NUL 预算 */
|
||||
meow_widget *meow_textfield_create(int x, int y, int w, int h, const char *placeholder,
|
||||
@@ -384,6 +394,11 @@ int meow_listview_set_item_tier(meow_widget *lv, int lines);
|
||||
/* 完全自绘:设 draw_item 回调(覆盖默认 renderer);NULL=用默认 renderer。返回 0=成功。 */
|
||||
int meow_listview_set_item_draw(meow_widget *lv, meow_listview_draw_fn draw,
|
||||
void *ctx);
|
||||
/* MD3 容器模式(默认 renderer 可选,P0 对齐):0=扁平满宽行+分隔线(默认,兼容);
|
||||
* 1=每行外套 surfaceContainer 圆角卡(12dp)+行间空隙,选中=primaryContainer/按压=primary α
|
||||
* (tonal,非满幅实心),去冗余分隔线;段头=surface 上的 primary 段标签(无卡无分隔线)。
|
||||
* 注意:仅对默认 renderer(未 set_item_draw)生效;完全自绘行由 App self-draw 自理。 */
|
||||
int meow_listview_set_container(meow_widget *lv, int on);
|
||||
/* 空态占位:count==0 时视口内居中画 empty_text(NULL 不画)。返回 0=成功。 */
|
||||
int meow_listview_set_empty_text(meow_widget *lv, const char *text);
|
||||
|
||||
|
||||
+119
-50
@@ -116,6 +116,7 @@ struct meow_widget {
|
||||
int show_icon; /* 1=画左图标/缩略图(默认 1) */
|
||||
int show_right;/* 1=画右尾件(默认 1) */
|
||||
char empty_text[64]; /* 空态占位文案(首字符 0=不画) */
|
||||
int container; /* MD3 容器模式(默认 renderer):1=行=surfaceContainer 圆角卡+空隙 (P0) */
|
||||
|
||||
/* §5.5 左滑删除(列表行横向手势:滑动偏移/删除动画/回弹;calloc 归零,安全)。
|
||||
* 手势由 App 在 on_touch_move 喂(swipe_begin/move/end);横向小位移判 swipe、纵向滚动优先;
|
||||
@@ -141,6 +142,12 @@ static uint32_t widget_fg(const meow_widget *w, const meow_theme *th, uint32_t d
|
||||
{ (void)th; return (w->opts_used && w->opts.fg) ? w->opts.fg : def; }
|
||||
static int widget_radius(const meow_widget *w, int def)
|
||||
{ return (w->opts_used && w->opts.radius >= 0) ? w->opts.radius : def; }
|
||||
/* MD3 全形按钮圆角 = 胶囊(全高一半);opts.radius 显式优先(P1 shape 对齐,替代硬编码 10)。 */
|
||||
static int widget_btn_radius(const meow_widget *w)
|
||||
{
|
||||
if (w->opts_used && w->opts.radius >= 0) return w->opts.radius;
|
||||
return MEOW_SHAPE_FULL(w->h);
|
||||
}
|
||||
static int widget_pady(const meow_widget *w)
|
||||
{ return (w->opts_used && w->opts.pad_y > 0) ? w->opts.pad_y : 0; }
|
||||
|
||||
@@ -1017,6 +1024,11 @@ int meow_list_tap_at(meow_widget *w, int x, int y)
|
||||
#define MEOW_LISTV_ICON 24 /* 图标盒尺寸(px) */
|
||||
#define MEOW_LISTV_PAD 16 /* 行内左右 padding(px) */
|
||||
#define MEOW_LISTV_SUB_GAP 2 /* 标题与副标题间隙(px) */
|
||||
/* MD3 容器模式(P0):行=surfaceContainer 圆角卡 + 行间空隙(去分隔线);卡图元与主界面/
|
||||
* ncm 歌单同手法(main_menu.c:639 / playlist.c)。卡在行高内上下对称内缩(行中心=卡中心)。 */
|
||||
#define MEOW_LISTV_CARD_MARGIN 8 /* 卡横向外边距(px) */
|
||||
#define MEOW_LISTV_CARD_GAP 8 /* 卡纵向间隙(px) */
|
||||
#define MEOW_LISTV_CARD_RADIUS 12 /* 卡圆角(px,12dp) */
|
||||
|
||||
/* meow_ui_img_scaled 弱引用:W_LISTVIEW 的 MEOW_LIST_ICON_IMG 分支用它绘制图片图标。
|
||||
* 弱引用让「只用内置符号图标、不解码图片」的 App 不被牵连进 meow_ui_img.o/stb_image.o
|
||||
@@ -1395,6 +1407,14 @@ int meow_listview_set_item_draw(meow_widget *w, meow_listview_draw_fn draw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int meow_listview_set_container(meow_widget *w, int on)
|
||||
{
|
||||
if (!w || w->type != W_LISTVIEW) return -1;
|
||||
w->container = on ? 1 : 0;
|
||||
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int meow_listview_set_empty_text(meow_widget *w, const char *text)
|
||||
{
|
||||
if (!w || w->type != W_LISTVIEW) return -1;
|
||||
@@ -1631,7 +1651,7 @@ void meow_widget_draw(meow_widget *w)
|
||||
uint32_t bg;
|
||||
if (fill) bg = (hold) ? state_tint(base, th, 24) : (press ? state_tint(base, th, 12) : base);
|
||||
else bg = 0;
|
||||
int r = widget_radius(w, 10);
|
||||
int r = widget_btn_radius(w);
|
||||
if (fill) meow_gfx_fill_round(w->x, w->y, w->w, w->h, r, bg);
|
||||
else if (press) meow_ui_fill_rect_alpha(w->x, w->y, w->w, w->h, th->primary, 12); /* transparent ripple */
|
||||
/* 内容区受 pad 垂直内缩(水平居中文本,pad_x 不影响中心) */
|
||||
@@ -1693,11 +1713,15 @@ void meow_widget_draw(meow_widget *w)
|
||||
break;
|
||||
}
|
||||
case W_SWITCH: {
|
||||
uint32_t bg = w->on ? th->primary : th->onSurfaceVariant;
|
||||
/* MD3(P3):on-track=primary;off-track=surfaceContainerHighest(原 onSurfaceVariant 过暗);
|
||||
* on-thumb=onPrimary;off-thumb=surface + outline(原恒白)。 */
|
||||
uint32_t bg = w->on ? th->primary : th->surfaceContainerHighest;
|
||||
meow_gfx_fill_round(w->x, w->y, w->w, w->h, w->h / 2, bg);
|
||||
int knob_r = w->h / 2 - 3;
|
||||
int kx = w->on ? w->x + w->w - knob_r * 2 - 3 : w->x + 3;
|
||||
meow_gfx_fill_round(kx, w->y + 3, knob_r * 2, knob_r * 2, knob_r, 0xFFFFFF);
|
||||
uint32_t knob = w->on ? th->onPrimary : th->surface; /* off-thumb 表面色 */
|
||||
meow_gfx_fill_round(kx, w->y + 3, knob_r * 2, knob_r * 2, knob_r, knob);
|
||||
if (!w->on) meow_ui_draw_rect_round(kx, w->y + 3, knob_r * 2, knob_r * 2, knob_r, th->outline);
|
||||
if (disabled) meow_gfx_fill_round_alpha(w->x, w->y, w->w, w->h, w->h / 2, th->onSurface, 90);
|
||||
break;
|
||||
}
|
||||
@@ -1777,11 +1801,16 @@ void meow_widget_draw(meow_widget *w)
|
||||
int vx0 = w->x, vy0 = w->y, vy1 = w->y + w->h;
|
||||
int thh = meow_ui_text_height(th->font_body);
|
||||
int pad = MEOW_LISTV_PAD, isz = MEOW_LISTV_ICON;
|
||||
int text_x = vx0 + pad + ((w->show_icon) ? (isz + pad) : 0); /* 无图标则无图标间隙 */
|
||||
int op_start = (w->show_right) ? (vx0 + (w->w * 2 / 3)) /* 行右 1/3 = 操作区 */
|
||||
: (vx0 + w->w - pad);
|
||||
/* 容器模式(P0):行=surfaceContainer 圆角卡,卡横向内缩 cm;内容左缘/操作区/可用宽
|
||||
* 都在卡内计算(非容器 cm=0 → 与既有行为逐字一致)。 */
|
||||
int cm = w->container ? MEOW_LISTV_CARD_MARGIN : 0;
|
||||
int cw = w->w - 2 * cm; /* 内容/卡宽 */
|
||||
int cx0 = vx0 + cm; /* 内容左缘(卡内) */
|
||||
int text_x = cx0 + pad + ((w->show_icon) ? (isz + pad) : 0); /* 无图标则无图标间隙 */
|
||||
int op_start = (w->show_right) ? (cx0 + (cw * 2 / 3)) /* 行右 1/3 = 操作区 */
|
||||
: (cx0 + cw - pad);
|
||||
int text_maxw = (w->show_right) ? (op_start - pad - text_x) /* 标题/副标题可用宽(不压操作区) */
|
||||
: ((vx0 + w->w - pad) - text_x);
|
||||
: ((cx0 + cw - pad) - text_x);
|
||||
if (text_maxw < 8) text_maxw = 8;
|
||||
|
||||
/* 空态占位(§5.5):count==0 且设了 empty_text → 视口内居中画文案。 */
|
||||
@@ -1841,26 +1870,36 @@ void meow_widget_draw(meow_widget *w)
|
||||
meow_str("common.delete"), th->font_body, th->onError);
|
||||
shift = w->swipe_dx;
|
||||
}
|
||||
int rlx = vx0 + shift; /* 行内容左移后的 x */
|
||||
int rlx = (w->container ? cx0 : vx0) + shift; /* 行内容/卡左缘(随行左移) */
|
||||
int rtx = text_x + shift; /* 文本 x(随行左移) */
|
||||
int rop = op_start + shift; /* 操作区分界 x */
|
||||
int card_y = ry + MEOW_LISTV_CARD_GAP / 2; /* 容器模式:卡顶(行内对称内缩) */
|
||||
int card_h = item - MEOW_LISTV_CARD_GAP;
|
||||
|
||||
if (it->section) { /* 段头占位行(非粘性):surfaceContainerHigh 底 + primary 段名 */
|
||||
meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->surfaceContainerHigh);
|
||||
if (it->section) { /* 段头占位行(非粘性):容器=surface 上的 primary 段标签;非容器=surfaceContainerHigh 底 */
|
||||
if (!w->container) meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->surfaceContainerHigh);
|
||||
int sty = ry + (item - thh) / 2;
|
||||
if (it->title && sty >= vy0 && sty + thh <= vy1)
|
||||
listv_text_trunc(rtx, sty, it->title, text_maxw, th->font_body, th->primary);
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
if (!it->enabled)
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
if (!w->container) {
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
if (!it->enabled)
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 选中/按压背景(primaryContainer / 半透明主题色按压层) */
|
||||
if (sel) meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->primaryContainer);
|
||||
else if (press) meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->primary, 26);
|
||||
/* 选中/按压背景(容器=卡内 tonal;非容器=满幅实心,原行为) */
|
||||
if (w->container) {
|
||||
meow_gfx_fill_round(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->surfaceContainer);
|
||||
if (sel) meow_gfx_fill_round(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->primaryContainer);
|
||||
else if (press) meow_gfx_fill_round_alpha(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->primary, 26);
|
||||
} else {
|
||||
if (sel) meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->primaryContainer);
|
||||
else if (press) meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->primary, 26);
|
||||
}
|
||||
uint32_t textcol = sel ? th->onPrimaryContainer : th->onSurface;
|
||||
uint32_t subcol = sel ? th->onPrimaryContainer : th->onSurfaceVariant;
|
||||
|
||||
@@ -1890,19 +1929,25 @@ void meow_widget_draw(meow_widget *w)
|
||||
|
||||
/* 右尾件(show_right=1:箭头/开关/复选/⋯) */
|
||||
if (w->show_right && it->right != MEOW_LIST_RIGHT_NONE) {
|
||||
int ax = rlx + w->w - pad - 24; /* 右缘动作槽(约 24px) */
|
||||
int ax = (cx0 + cw - pad - 24) + shift; /* 右缘动作槽(约 24px;容器=卡内右缘) */
|
||||
if (ax >= rop)
|
||||
listv_draw_right(th, ax, ry, item, it->right, it->on, subcol);
|
||||
}
|
||||
|
||||
/* 分隔线(仅落在可见带内才画) */
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
/* 分隔线(仅非容器画;容器模式去冗余分隔线,行间用空隙替代) */
|
||||
if (!w->container) {
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
}
|
||||
|
||||
/* 禁用行整体变淡(§5.5/§5.8.3 enabled=0 → 变暗) */
|
||||
if (!it->enabled)
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
/* 禁用行整体变淡(§5.5/§5.8.3 enabled=0 → 变暗;容器=卡内淡) */
|
||||
if (!it->enabled) {
|
||||
if (w->container)
|
||||
meow_gfx_fill_round_alpha(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->onSurface, 90);
|
||||
else
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1918,10 +1963,13 @@ void meow_widget_draw(meow_widget *w)
|
||||
int cl = ry > vy0 ? ry : vy0; /* 可见顶界(裁剪用) */
|
||||
int cr = (ry + item) < vy1 ? (ry + item) : vy1; /* 可见底界 */
|
||||
int sel = (i == w->sel);
|
||||
int press = meow_input_touch_down() &&
|
||||
meow_input_touch_x() >= vx0 && meow_input_touch_x() < vx0 + w->w &&
|
||||
meow_input_touch_y() >= ry && meow_input_touch_y() < ry + item;
|
||||
uint32_t textcol = sel ? th->onPrimaryContainer : th->onSurface;
|
||||
uint32_t subcol = sel ? th->onPrimaryContainer : th->onSurfaceVariant;
|
||||
/* 左滑删除(M7.3):本行被滑动 → 右露删除区 + 行 x 左移。非滑动行 shift=0 → 输出不变。 */
|
||||
int shift = 0, rlx = vx0, rtx = text_x, rop = op_start;
|
||||
int shift = 0, rlx = (w->container ? cx0 : vx0), rtx = text_x, rop = op_start;
|
||||
if (w->swipe_active && w->swipe_idx == i && w->swipe_dx < 0) {
|
||||
meow_ui_fill_rect(vx0 + w->w + w->swipe_dx, ry, -w->swipe_dx, item, th->error);
|
||||
int thh2 = meow_ui_text_height(th->font_body);
|
||||
@@ -1929,9 +1977,19 @@ void meow_widget_draw(meow_widget *w)
|
||||
if (dly >= vy0 && dly + thh2 <= vy1)
|
||||
meow_ui_text_center(vx0 + w->w + w->swipe_dx + (-w->swipe_dx) / 2, dly,
|
||||
meow_str("common.delete"), th->font_body, th->onError);
|
||||
shift = w->swipe_dx; rlx = vx0 + shift; rtx = text_x + shift; rop = op_start + shift;
|
||||
shift = w->swipe_dx; rlx = (w->container ? cx0 : vx0) + shift;
|
||||
rtx = text_x + shift; rop = op_start + shift;
|
||||
}
|
||||
int card_y = ry + MEOW_LISTV_CARD_GAP / 2;
|
||||
int card_h = item - MEOW_LISTV_CARD_GAP;
|
||||
if (w->container) {
|
||||
meow_gfx_fill_round(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->surfaceContainer);
|
||||
if (sel) meow_gfx_fill_round(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->primaryContainer);
|
||||
else if (press) meow_gfx_fill_round_alpha(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->primary, 26);
|
||||
} else {
|
||||
if (sel) meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->primaryContainer);
|
||||
else if (press) meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->primary, 26);
|
||||
}
|
||||
if (sel) meow_ui_fill_rect(rlx, cl, w->w, cr - cl, th->primaryContainer);
|
||||
|
||||
/* 图标(左) */
|
||||
uint32_t iccol = sel ? th->onPrimaryContainer
|
||||
@@ -1958,19 +2016,25 @@ void meow_widget_draw(meow_widget *w)
|
||||
|
||||
/* 右侧操作区 */
|
||||
if (it.right != MEOW_LIST_RIGHT_NONE) {
|
||||
int ax = rlx + w->w - pad - 24; /* 右缘动作槽(约 24px) */
|
||||
int ax = (cx0 + cw - pad - 24) + shift; /* 右缘动作槽(约 24px;容器=卡内右缘) */
|
||||
if (ax >= rop)
|
||||
listv_draw_right(th, ax, ry, item, it.right, it.on, subcol);
|
||||
}
|
||||
|
||||
/* 分隔线(仅落在可见带内才画) */
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
/* 分隔线(仅非容器画;容器模式去冗余分隔线,行间用空隙替代) */
|
||||
if (!w->container) {
|
||||
int sy = ry + item - 1;
|
||||
if (sy >= cl && sy < cr)
|
||||
meow_ui_fill_rect(rlx, sy, w->w, 1, th->outlineVariant);
|
||||
}
|
||||
|
||||
/* 禁用行整体变淡(§5.5/§5.8.3 enabled=0 → 变暗) */
|
||||
if (!it.enabled)
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
/* 禁用行整体变淡(§5.5/§5.8.3 enabled=0 → 变暗;容器=卡内淡) */
|
||||
if (!it.enabled) {
|
||||
if (w->container)
|
||||
meow_gfx_fill_round_alpha(rlx, card_y, cw, card_h, MEOW_LISTV_CARD_RADIUS, th->onSurface, 90);
|
||||
else
|
||||
meow_ui_fill_rect_alpha(rlx, cl, w->w, cr - cl, th->onSurface, 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (disabled) meow_ui_fill_rect_alpha(w->x, w->y, w->w, w->h, th->onSurface, 90);
|
||||
@@ -1988,7 +2052,7 @@ void meow_widget_draw(meow_widget *w)
|
||||
break;
|
||||
case W_TEXTFIELD: {
|
||||
/* MD3 输入框:圆角外框(surfaceContainerLowest 底 + outline 描边;focused=primary 2px)+ 提示/文本 + 光标。 */
|
||||
int r = widget_radius(w, 8);
|
||||
int r = widget_radius(w, MEOW_SHAPE_SMALL);
|
||||
int focused = (w->state & MEOW_WS_FOCUSED) != 0;
|
||||
meow_gfx_fill_round(w->x, w->y, w->w, w->h, r, th->surfaceContainerLowest);
|
||||
uint32_t bcol = focused ? th->primary : th->outline;
|
||||
@@ -2045,26 +2109,30 @@ void meow_widget_draw(meow_widget *w)
|
||||
break;
|
||||
}
|
||||
case W_CHECKBOX: {
|
||||
/* MD3(P3):视觉字 24dp 于控件矩形内居中(触摸目标不变);修正原 34 视觉过大。 */
|
||||
int sel = (w->state & MEOW_WS_SELECTED) != 0;
|
||||
int sz = w->w;
|
||||
int r = widget_radius(w, 4);
|
||||
int sz = 24;
|
||||
if (w->w < sz) sz = w->w; /* 控件小于视觉尺寸时跟随 */
|
||||
int bx = w->x + (w->w - sz) / 2, by = w->y + (w->h - sz) / 2;
|
||||
int r = widget_radius(w, MEOW_SHAPE_EXTRASMALL);
|
||||
if (sel) {
|
||||
meow_gfx_fill_round(w->x, w->y, sz, sz, r, th->primary);
|
||||
int ax = w->x + 9, ay1 = w->y + 17, ay2 = w->y + 23, bx = w->x + 15, cx = w->x + 25, cy = w->y + 11;
|
||||
meow_gfx_line(ax, ay1, bx, ay2, 3, th->onPrimary);
|
||||
meow_gfx_line(bx, ay2, cx, cy, 3, th->onPrimary);
|
||||
meow_gfx_fill_round(bx, by, sz, sz, r, th->primary);
|
||||
int ax = bx + 7, ay1 = by + 13, ay2 = by + 17, b2 = bx + 11, cx = bx + 18, cy = by + 7;
|
||||
meow_gfx_line(ax, ay1, b2, ay2, 2, th->onPrimary);
|
||||
meow_gfx_line(b2, ay2, cx, cy, 2, th->onPrimary);
|
||||
} else {
|
||||
meow_ui_draw_rect_round(w->x, w->y, sz, sz, r, th->outline);
|
||||
meow_ui_draw_rect_round(bx, by, sz, sz, r, th->outline);
|
||||
}
|
||||
if (w->state & MEOW_WS_FOCUSED) meow_ui_draw_rect_round(w->x, w->y, sz, sz, r, th->primary);
|
||||
if (disabled) meow_gfx_fill_round_alpha(w->x, w->y, sz, sz, r, th->onSurface, 90);
|
||||
if (w->state & MEOW_WS_FOCUSED) meow_ui_draw_rect_round(bx, by, sz, sz, r, th->primary);
|
||||
if (disabled) meow_gfx_fill_round_alpha(bx, by, sz, sz, r, th->onSurface, 90);
|
||||
break;
|
||||
}
|
||||
case W_RADIO: {
|
||||
/* MD3(P3):视觉 20dp(环半径 10)于控件内居中;原环半径 12 略大。 */
|
||||
int sel = (w->state & MEOW_WS_SELECTED) != 0;
|
||||
int ccx = w->x + w->w / 2, ccy = w->y + w->h / 2;
|
||||
meow_gfx_ring_arc(ccx, ccy, 12, 2, 0, 360, sel ? th->primary : th->outline);
|
||||
if (sel) meow_gfx_fill_circle(ccx, ccy, 6, th->primary);
|
||||
meow_gfx_ring_arc(ccx, ccy, 10, 2, 0, 360, sel ? th->primary : th->outline);
|
||||
if (sel) meow_gfx_fill_circle(ccx, ccy, 5, th->primary);
|
||||
if (disabled) meow_gfx_fill_round_alpha(w->x, w->y, w->w, w->h, w->w / 2, th->onSurface, 90);
|
||||
break;
|
||||
}
|
||||
@@ -2154,7 +2222,8 @@ void meow_widget_draw(meow_widget *w)
|
||||
for (int i = 0; i < w->nitems; i++) {
|
||||
int ix = w->x + i * iw;
|
||||
int sel = (i == w->selected);
|
||||
if (sel) meow_gfx_fill_round(ix + iw / 2 - 24, w->y + 8, 48, 22, 11, th->secondaryContainer);
|
||||
if (sel) /* MD3 active pill 64×32(原 48×22 偏小);垂直居中于栏 */
|
||||
meow_gfx_fill_round(ix + iw / 2 - 32, w->y + (w->h - 32) / 2, 64, 32, 16, th->secondaryContainer);
|
||||
uint32_t col = sel ? th->onSecondaryContainer : th->onSurfaceVariant;
|
||||
meow_ui_text_center(ix + iw / 2, ay, w->items[i], th->font_body, col);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/* test_meow_md3.c — 宿主验证 MD3(Material You)对齐修复(agent-434 P0/P1/P3):
|
||||
* P0 listview 容器模式(默认 renderer:行=surfaceContainer 圆角卡 + 行间空隙 + 去分隔线);
|
||||
* P1 按钮胶囊化(圆角=h/2);
|
||||
* P3 Switch off-track/off-thumb、NavigationBar active pill 64×32、Checkbox/Radio 视觉尺寸。
|
||||
* 断言全部「画完读 back_buf 像素」(region_has/px_near),不依赖 /dev/fb0/字库(meow_font 打桩)。
|
||||
*
|
||||
* 编译(宿主 gcc,链真实 gfx/sys/theme/vol/log/widget/input/activity/dialog/ime + 打桩 font/global):
|
||||
* gcc -Wall -Wextra -o test_meow_md3 test_meow_md3.c test_host_stub.c \
|
||||
* meow_ui_gfx.c meow_ui_sys.c meow_ui_theme.c meow_ui_vol.c meow_ui_log.c \
|
||||
* meow_ui_widget.c meow_ui_input.c meow_ui_activity.c meow_ui_dialog.c meow_ui_ime.c meow_ui_str.c \
|
||||
* meow_pinyin.c meow_ui_draw.c meow_ui_view.c meow_ui_box.c meow_ui_anim.c meow_ui_scroll.c \
|
||||
* meow_ui_img.c meow_ui_media.c meow_notify_ipc.c stb_image.c \
|
||||
* -I. -I../meow_launcherd -DMEOW_UI_HOST_TEST -pthread -lm
|
||||
* 运行:./test_meow_md3
|
||||
*/
|
||||
#include "meow_ui.h"
|
||||
#include "meow_ui_internal.h" /* meow_ui_back_buf/pitch/bpp */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void rd_px(int x, int y, int *r, int *g, int *b)
|
||||
{
|
||||
unsigned char *bb = meow_ui_back_buf();
|
||||
int line = meow_ui_back_buf_pitch(), bpp = meow_ui_back_buf_bpp();
|
||||
if (!bb || x < 0 || y < 0) { *r = *g = *b = 0; return; }
|
||||
if (bpp == 16) {
|
||||
uint16_t px = *(uint16_t *)(bb + (size_t)y * line + (size_t)x * 2);
|
||||
*r = (((px >> 11) & 0x1F) << 3) | ((px >> 11) & 0x1F) >> 2;
|
||||
*g = (((px >> 5) & 0x3F) << 2) | ((px >> 5) & 0x3F) >> 4;
|
||||
*b = ((px & 0x1F) << 3) | ((px & 0x1F) >> 2);
|
||||
} else {
|
||||
uint32_t px = *(uint32_t *)(bb + (size_t)y * line + (size_t)x * 4);
|
||||
*r = (px >> 16) & 0xFF; *g = (px >> 8) & 0xFF; *b = px & 0xFF;
|
||||
}
|
||||
}
|
||||
static int near2(int a, int b) { int d = a - b; if (d < 0) d = -d; return d <= 12; }
|
||||
static int px_near(int x, int y, int r, int g, int b)
|
||||
{
|
||||
int rr, gg, bb; rd_px(x, y, &rr, &gg, &bb);
|
||||
return near2(rr, r) && near2(gg, g) && near2(bb, b);
|
||||
}
|
||||
#define UNPK(c, rr, gg, bb) do { (rr) = ((c) >> 16) & 0xFF; (gg) = ((c) >> 8) & 0xFF; (bb) = (c) & 0xFF; } while (0)
|
||||
|
||||
/* Listview src2 数据源:2 行普通富 item(无图标、无右尾件,label-only)。 */
|
||||
typedef struct { const char *title; const char *sub; int right; int enabled; } trow_t;
|
||||
static trow_t g_rows[2] = {
|
||||
{ "Row 0", NULL, MEOW_LIST_RIGHT_NONE, 1 },
|
||||
{ "Row 1", NULL, MEOW_LIST_RIGHT_NONE, 1 },
|
||||
};
|
||||
static int trow_src(int idx, meow_list_item *out, void *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if (idx < 0 || idx >= 2) return 0;
|
||||
out->icon_kind = MEOW_LIST_ICON_NONE;
|
||||
out->title = g_rows[idx].title;
|
||||
out->subtitle = g_rows[idx].sub;
|
||||
out->right = g_rows[idx].right;
|
||||
out->on = 0;
|
||||
out->enabled = g_rows[idx].enabled;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setenv("MEOW_UI_DUMP", "/tmp/md3.ppm", 1);
|
||||
meow_ui_opts o = { 480, 720 };
|
||||
assert(meow_ui_init(&o) == 0);
|
||||
assert(meow_ui_width() == 480 && meow_ui_height() == 720);
|
||||
const meow_theme *th = meow_theme_get();
|
||||
int sf_r, sf_g, sf_b, sc_r, sc_g, sc_b, p_r, p_g, p_b;
|
||||
int pc_r, pc_g, pc_b, ov_r, ov_g, ov_b, sch_r, sch_g, sch_b, scs_r, scs_g, scs_b;
|
||||
UNPK(th->surface, sf_r, sf_g, sf_b);
|
||||
UNPK(th->surfaceContainer, sc_r, sc_g, sc_b);
|
||||
UNPK(th->primary, p_r, p_g, p_b);
|
||||
UNPK(th->primaryContainer, pc_r, pc_g, pc_b);
|
||||
UNPK(th->outline, ov_r, ov_g, ov_b);
|
||||
UNPK(th->surfaceContainerHighest, sch_r, sch_g, sch_b);
|
||||
UNPK(th->secondaryContainer, scs_r, scs_g, scs_b);
|
||||
|
||||
/* ---- P0 listview 容器模式:行=surfaceContainer 圆角卡 + 空隙,去分隔线 ---- */
|
||||
meow_widget *lv = meow_listview_create(20, 240, 320, 112, 2, trow_src, NULL, MEOW_LIST_SEL_SINGLE);
|
||||
assert(lv);
|
||||
assert(meow_listview_set_item_h(lv, 56) == 56);
|
||||
assert(meow_listview_set_container(lv, 1) == 0);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(lv);
|
||||
/* 行 0 卡(x=28,y=244,w=304,h=48):中心=surfaceContainer;行 1 同。 */
|
||||
assert(px_near(180, 268, sc_r, sc_g, sc_b));
|
||||
assert(px_near(180, 324, sc_r, sc_g, sc_b));
|
||||
/* 卡间空隙(y=292..300):surface(行间分隔用空隙)。 */
|
||||
assert(px_near(180, 296, sf_r, sf_g, sf_b));
|
||||
/* 去分隔线:行边界不再画 outlineVariant(改空隙代替)。 */
|
||||
assert(!px_near(180, 292, ov_r, ov_g, ov_b));
|
||||
/* 选中行 0 → primaryContainer(tonal,非满幅实心)。 */
|
||||
meow_listview_set_sel(lv, 0);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(lv);
|
||||
assert(px_near(180, 268, pc_r, pc_g, pc_b));
|
||||
assert(px_near(180, 324, sc_r, sc_g, sc_b)); /* 行 1 未选仍卡 */
|
||||
printf("PASS listview container: rounded card + gap + no-divider + tonal select\n");
|
||||
|
||||
/* ---- P1 按钮胶囊化:圆角=h/2(56/2=28)---- */
|
||||
meow_widget *btn = meow_btn_create_variant(10, 10, 200, 56, "FILLED", MEOW_BTN_FILLED);
|
||||
assert(btn);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(btn);
|
||||
assert(px_near(110, 22, p_r, p_g, p_b)); /* 上部(避开文字)=primary */
|
||||
/* 顶缘中心在圆角胶囊内(仍 primary);角落(圆角外)回 surface。 */
|
||||
assert(px_near(110, 13, p_r, p_g, p_b));
|
||||
assert(px_near(12, 12, sf_r, sf_g, sf_b)); /* 角落被圆角切掉 */
|
||||
/* 同高矮按钮(h=40 → 圆角 20):上部仍 primary,角落 surface。 */
|
||||
meow_widget *btn2 = meow_btn_create_variant(10, 120, 120, 40, "B", MEOW_BTN_FILLED);
|
||||
assert(btn2);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(btn2);
|
||||
assert(px_near(70, 125, p_r, p_g, p_b));
|
||||
assert(px_near(12, 122, sf_r, sf_g, sf_b));
|
||||
printf("PASS button: capsule radius = h/2\n");
|
||||
|
||||
/* ---- P3 Switch off-track/off-thumb ---- */
|
||||
meow_widget *sw = meow_switch_create(20, 300, 0); /* off */
|
||||
assert(sw);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(sw);
|
||||
assert(px_near(60, 316, sch_r, sch_g, sch_b)); /* off-track=surfaceContainerHighest */
|
||||
assert(px_near(36, 316, sf_r, sf_g, sf_b)); /* off-thumb=surface(表面色,非恒白) */
|
||||
meow_switch_set(sw, 1);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(sw);
|
||||
assert(px_near(28, 316, p_r, p_g, p_b)); /* on-track=primary(thumb 左侧) */
|
||||
printf("PASS switch: off-track surfaceContainerHighest / off-thumb surface\n");
|
||||
|
||||
/* ---- P3 NavigationBar active pill 64×32 ---- */
|
||||
meow_widget *nb = meow_navigationbar_create(0, 600, 480, 80);
|
||||
assert(nb);
|
||||
meow_navigationbar_add_item(nb, "A");
|
||||
meow_navigationbar_add_item(nb, "B");
|
||||
meow_navigationbar_add_item(nb, "C");
|
||||
meow_navigationbar_add_item(nb, "D");
|
||||
meow_navigationbar_set_selected(nb, 0);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(nb);
|
||||
/* item0 pill 中心 (ix+60, y+40)=(60,640) — 64×32 居中于栏;pill 内=secondaryContainer。 */
|
||||
assert(px_near(60, 640, scs_r, scs_g, scs_b));
|
||||
/* pill 外(栏上部)= surfaceContainer(navbar 容器底)。 */
|
||||
assert(px_near(60, 610, sc_r, sc_g, sc_b));
|
||||
printf("PASS navbar: active pill 64x32 (was 48x22)\n");
|
||||
|
||||
/* ---- P3 Checkbox 视觉 24dp(原 34 偏大):勾选框视觉居中,角落回 surface ---- */
|
||||
meow_widget *ck = meow_checkbox_create(150, 60);
|
||||
assert(ck);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(ck);
|
||||
/* 未选:24dp 描边框(左缘=150+5=155);框边=outline;内部=surface(空心)。 */
|
||||
assert(px_near(155, 77, ov_r, ov_g, ov_b)); /* 框左缘 stroke */
|
||||
assert(px_near(167, 77, sf_r, sf_g, sf_b)); /* 内部空心 */
|
||||
meow_widget_set_selected(ck, 1);
|
||||
meow_ui_clear(th->surface);
|
||||
meow_widget_draw(ck);
|
||||
/* 选中:24dp 实心 primary 居中(左缘 155..179 顶 65..89);控件矩形角落(视觉 24 外)不填。 */
|
||||
assert(px_near(150, 60, sf_r, sf_g, sf_b)); /* 视觉 24 外 → surface */
|
||||
assert(px_near(167, 77, p_r, p_g, p_b)); /* 视觉中心=primary */
|
||||
printf("PASS checkbox: 24dp visual (was 34)\n");
|
||||
|
||||
meow_widget_free(lv); meow_widget_free(btn); meow_widget_free(btn2);
|
||||
meow_widget_free(sw); meow_widget_free(nb); meow_widget_free(ck);
|
||||
printf("ALL MD3 PASS\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user