feat(sdk): M6.39批 — LazyGrid/LazyColumn/LazyRow MD3容器化 + SDK全局App内底部上滑回桌面(系统手势优先)

- meow_ui_widget.c: W_LIST/meow_list/LazyColumn/LazyRow默认container=1(MD3圆角卡surfaceContainer+tonal选中+卡内按压+去分隔线) + 新增meow_list_set_container; 平坦回退set_container(0)
- meow_lazygrid.c: lg_draw_cell容器化(卡内缩8,surfaceContainer圆角+tonal选中+按压)
- meow_ui_input.c: 新增meow_ui_input_is_home_swipe(镜像np_home_gesture:屏底28px热区+上移65px+竖向主导,与左缘返回/列表中滑互斥) + MEOW_EV_HOME分发→meow_ui_nav_request_exit(系统保留手势**优先于App on_swipe**,任意App内生效→MSG_NAV EXIT→批①保活回桌面; 不调request_exit避免进程退出断送保活)
- 声明: meow_ui_input.h / meow_ui_widgets.h 各追加
- 宿主测试: test_meow_ui_home_gesture 19-0 / test_meow_ui_lazygrid 32-0, 0warning
This commit is contained in:
AskaEth committed 2026-09-04 13:56:11 +08:00
1 parent d0a5901ffb
commit 501867b362
7 files changed
+350 -32

No files matched your search

+63 -10
View File
@@ -407,6 +407,10 @@ meow_widget *meow_list_create(int x, int y, int w, int h, int count,
t->owner = meow_ui_activity_active();
t->state = MEOW_WS_ENABLED;
t->count = count; t->src = src; t->ctx = ctx; t->sel = 0;
/* M6.37 P1:SDK 默认列表(meow_list_create / meow_lazycolumn_create / meow_lazyrow_create,皆 W_LIST)
* 走 MD3 容器模式——每项=surfaceContainer 圆角卡 + 项间空隙 + 去分隔线 + 卡内 tonal 选中/按压,
* 与 meow_listview 容器同范式(全局统一)。需扁平的宿主可显式 meow_list_set_container(w,0) 回退。 */
t->container = 1;
meow_draw_widget_register(t);
return t;
}
@@ -1014,6 +1018,17 @@ int meow_list_tap_at(meow_widget *w, int x, int y)
return idx;
}
/* MD3 容器模式(W_LIST 共用,§5.5/§5.8.6):0=扁平满宽项+分隔线(回退);1=每项外套 surfaceContainer
* 圆角卡+项间空隙(去分隔线),选中=primaryContainer/按压=primary α26(卡内 tonal)。
* 覆盖 meow_list_create / meow_lazycolumn_create / meow_lazyrow_create。返回 0=成功;无效=负值。 */
int meow_list_set_container(meow_widget *w, int on)
{
if (!w || w->type != W_LIST) return -1;
w->container = on ? 1 : 0;
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
return 0;
}
/* ============================================================ */
/* §5.5 结构化列表(W_LISTVIEW):行=图标+标题+副标题+右侧操作+选中
* ------------------------------------------------------------
@@ -1730,7 +1745,11 @@ void meow_widget_draw(meow_widget *w)
}
case W_LIST: {
/* §5.8.6 列表容器(LazyColumn/LazyRow):只画可见项(虚拟化)+ 滚动偏移。
* 纵向=行高 item_h(默认 44,兼容既有 meow_list_create);横向=LazyRow(列宽=item_h)。 */
* 纵向=行高 item_h(默认 44,兼容既有 meow_list_create);横向=LazyRow(列宽=item_h)。
* MD3 容器模式(w->container=1,默认):每项外套 surfaceContainer 圆角卡(12dp)+ 项间空隙
* (去分隔线),选中=primaryContainer/按压=primary α26(卡内 tonal),与 meow_listview 容器同范式;
* 卡在项内交叉轴内缩 MEOW_LISTV_CARD_MARGIN、滚动轴对称内缩 MEOW_LISTV_CARD_GAP(行中心=卡中心)。
* 非容器(meow_list_set_container(0) 回退):满幅扁平行 + primary 选中 + onSurfaceVariant 分隔线。 */
int pad = 16;
int item = list_item(w);
int vp = w->horizontal ? w->w : w->h;
@@ -1747,36 +1766,70 @@ void meow_widget_draw(meow_widget *w)
* 画到视口外 → 标脏并上屏 → 标题栏/底部残留脏区,P3)。 */
int vx0 = w->x, vy0 = w->y, vx1 = w->x + w->w, vy1 = w->y + w->h;
int thh = meow_ui_text_height(th->font_body);
int cm = w->container ? MEOW_LISTV_CARD_MARGIN : 0; /* 卡交叉轴内缩(纵向=水平→横向=垂直) */
int cgap = w->container ? MEOW_LISTV_CARD_GAP : 0; /* 卡滚动轴对称内缩(去分隔线、留空隙) */
for (int i = first; i < last; i++) {
char label[64] = "";
if (!w->src || !w->src(i, label, (int)sizeof label, w->ctx)) continue;
int pos = i * item - off; /* 相对容器起点的可视位置 */
int sel = (i == w->sel);
if (w->horizontal) {
int rx = w->x + pos;
if (rx >= vx1) break; /* 完全在右缘外 */
if (rx + item <= vx0) continue; /* 完全在左缘外(滚出残余) */
int cl = rx > vx0 ? rx : vx0; /* 可见左界 */
int cr = (rx + item) < vx1 ? (rx + item) : vx1; /* 可见右界 */
if (i == w->sel) meow_ui_fill_rect(cl, w->y, cr - cl, w->h, th->primary);
uint32_t col = (i == w->sel) ? 0xFFFFFF : th->onSurface;
int ctop = w->y + cm; /* 卡顶(交叉轴内缩) */
int chh = w->h - 2 * cm; /* 卡高 */
int clft = rx + cgap / 2; /* 卡左(滚动轴对称内缩) */
int cwid = item - cgap; /* 卡宽 */
int press = meow_input_touch_down() &&
meow_input_touch_x() >= rx && meow_input_touch_x() < rx + item &&
meow_input_touch_y() >= w->y && meow_input_touch_y() < w->y + w->h;
if (w->container) {
meow_gfx_fill_round(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->surfaceContainer);
if (sel) meow_gfx_fill_round(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->primaryContainer);
else if (press) meow_gfx_fill_round_alpha(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->primary, 26);
} else {
if (sel) meow_ui_fill_rect(cl, w->y, cr - cl, w->h, th->primary);
}
uint32_t col = sel ? (w->container ? th->onPrimaryContainer : 0xFFFFFF) : th->onSurface;
int ty = w->y + (w->h - thh) / 2;
if (rx >= vx0 && rx + item <= vx1) /* 仅整项可见才画文本(防泄漏) */
meow_ui_text_center(rx + item / 2, ty, label, th->font_body, col);
int sxp = rx + item - 1; /* 分隔线:仅当落在可见区 */
if (sxp >= cl && sxp < cr) meow_ui_fill_rect(sxp, w->y, 1, w->h, th->onSurfaceVariant);
if (!w->container) { /* 非容器才画分隔线(容器模式去冗余) */
int sxp = rx + item - 1; /* 分隔线:仅当落在可见区 */
if (sxp >= cl && sxp < cr) meow_ui_fill_rect(sxp, w->y, 1, w->h, th->onSurfaceVariant);
}
} else {
int ry = w->y + pos;
if (ry >= vy1) break; /* 完全在底缘外 */
if (ry + item <= vy0) continue; /* 完全在顶缘外(滚出残余) */
int cl = ry > vy0 ? ry : vy0; /* 可见顶界 */
int cr = (ry + item) < vy1 ? (ry + item) : vy1; /* 可见底界 */
if (i == w->sel) meow_ui_fill_rect(w->x, cl, w->w, cr - cl, th->primary);
uint32_t col = (i == w->sel) ? 0xFFFFFF : th->onSurface;
int clft = w->x + cm; /* 卡左(交叉轴内缩) */
int cwid = w->w - 2 * cm; /* 卡宽 */
int ctop = ry + cgap / 2; /* 卡顶(滚动轴对称内缩) */
int chh = item - cgap; /* 卡高 */
int press = meow_input_touch_down() &&
meow_input_touch_x() >= w->x && meow_input_touch_x() < w->x + w->w &&
meow_input_touch_y() >= ry && meow_input_touch_y() < ry + item;
if (w->container) {
meow_gfx_fill_round(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->surfaceContainer);
if (sel) meow_gfx_fill_round(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->primaryContainer);
else if (press) meow_gfx_fill_round_alpha(clft, ctop, cwid, chh, MEOW_LISTV_CARD_RADIUS, th->primary, 26);
} else {
if (sel) meow_ui_fill_rect(w->x, cl, w->w, cr - cl, th->primary);
}
uint32_t col = sel ? (w->container ? th->onPrimaryContainer : 0xFFFFFF) : th->onSurface;
int txx = (w->container ? clft : w->x) + pad; /* 卡内文本左缘 */
int ty = ry + (item - thh) / 2;
if (ty >= vy0 && ty + thh <= vy1) /* 文本不越界才画(防标题/底部泄漏) */
meow_ui_text(w->x + pad, ty, label, th->font_body, col);
int sy = ry + item - 1; /* 分隔线:仅当落在可见区 */
if (sy >= cl && sy < cr) meow_ui_fill_rect(w->x, sy, w->w, 1, th->onSurfaceVariant);
meow_ui_text(txx, ty, label, th->font_body, col);
if (!w->container) { /* 非容器才画分隔线(容器模式去冗余) */
int sy = ry + item - 1; /* 分隔线:仅当落在可见区 */
if (sy >= cl && sy < cr) meow_ui_fill_rect(w->x, sy, w->w, 1, th->onSurfaceVariant);
}
}
}
if (disabled) meow_ui_fill_rect_alpha(w->x, w->y, w->w, w->h, th->onSurface, 90);