SDK 冲刺批①+②+⑤: meow_box 线性布局 + meow_anim 动画基座 + meow_scroll 滚动物理

- meow_box(include/meow_ui_box.h + meow_ui_box.c):竖直/水平容器;子项=固定|weight|wrap;
  margin/padding/gap;主轴对齐 start/center/end/space-between/around/evenly;交叉轴 start/center/end/stretch;
  嵌套(深度≤16 静态栈,单遍求解,无递归爆炸)。可作 meow_view 布局提供者
  (meow_view_set_layout/relayout,opt-in;未设布局的 view 保持现有绝对坐标行为)。
  新增 meow_widget_set_rect(只写字段不标脏)作为 box 写坐标的通道。
- meow_anim(include/meow_ui_anim.h + meow_ui_anim.c):时间驱动 tween(from/to/duration/easing:
  linear/ease-out/ease-in-out/overshoot)+ update/done 回调;静态池≤16、取消、并行多动画;
  meow_anim_set_region 让每帧只 flush 动画影响区(不整屏)。meow_anim_tick 挂主循环 on_tick,
  无动画零开销(只查计数即返回)。
- meow_scroll(include/meow_ui_scroll.h + meow_ui_scroll.c):速度跟踪(最近 N 采样加权)+ 松手 fling
  (减速度曲线,用 anim 基座驱动)+ 边界过冲 clamp + 简单回弹(不做 spring)+ 可选 snap;
  跟手拖动行为不变(track 内部调既有 set_scroll);每帧只 redraw 列表视口区;不引 libm。
- 追加式:既有 meow_row/column/box 与全部 meow_*_create/hit/scroll 签名一行未改;旧绝对坐标永远有效;
  既有 App 免改源码。
- 验证:宿主新测试 box(42)/anim(32)/scroll(17) 全 PASS;既存 9 回归(widgets/sdk_input_keys/ime_fix/
  pinyin/overlay_suppress/notif_gesture/sdk_fixes/sb_collapse/p1p2p3_repro)全 PASS;
  离屏 demo(demo_box_scroll.c)渲染 box 布局 + 列表 fling 正常;zig-mipsel -Wall -Wextra 全 TU 0 warning;
  meow_ui.a md5 83dd6a2d0d24cc748a8659c29f1de2b5(未重链/部署 hello/files/ncm/reader,由主会话统一处理)。
This commit is contained in:
MeowOS committed 2026-09-01 23:49:24 +08:00
1 parent 553a7d5d9e
commit 5a5e995ebd
19 files changed
+1839 -2

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
/* demo_box_scroll.c — 宿主离屏 demo:§12.1 meow_box 布局 + §12.3 meow_scroll fling 端到端。
* 渲染一屏「标题(固定) / 列表(weight 撑满) / 底栏(固定)」的 box 布局(cross 拉伸),
* 再对列表跑一次 fling(速度跟踪→惯性滑动到停止处),并 dump PPM 供目检。
*
* 编译(宿主 gcc,链真实 SDK 源 + 打桩 font/global):
* gcc -o demo_box_scroll demo_box_scroll.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_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
* 运行:MEOW_UI_DUMP=/tmp/demo_box.ppm ./demo_box_scroll
*/
#include "meow_ui.h"
#include "meow_ui_internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define NROW 60
#define ITEM 44
static int src(int idx, char *label, int len, void *ctx)
{
(void)ctx;
if (idx < 0 || idx >= NROW) return 0;
snprintf(label, (size_t)len, "item %d", idx);
return 1;
}
int main(void)
{
/* 离屏 dump */
setenv("MEOW_UI_DUMP", "/tmp/demo_box.ppm", 1);
meow_ui_opts o = { 480, 720 };
if (meow_ui_init(&o) != 0) { printf("DEMO FAIL: init\n"); return 1; }
const meow_theme *th = meow_theme_get();
meow_ui_clear(th->bg);
/* ---- box 布局:标题(固定) / 列表(weight) / 底栏(固定),交叉轴拉伸 ---- */
meow_box *bx = meow_box_new(MEOW_BOX_V);
meow_box_set_rect(bx, 0, 0, 480, 720);
meow_box_set_padding(bx, 12, 12, 12, 12);
meow_box_set_gap(bx, 8);
meow_box_set_align(bx, MEOW_BOX_ALIGN_START, MEOW_BOX_CROSS_STRETCH);
meow_widget *header = meow_btn_create(0, 0, 480, 44, "Header (fixed)");
meow_widget *list = meow_list_create(0, 0, 480, 100, NROW, src, NULL);
meow_list_set_item_h(list, ITEM);
meow_widget *footer = meow_btn_create(0, 0, 480, 52, "Footer (fixed)");
meow_box_add(bx, header, MEOW_BOX_FIXED, 0);
meow_box_add(bx, list, MEOW_BOX_WEIGHT, 1);
meow_box_add(bx, footer, MEOW_BOX_FIXED, 0);
meow_box_arrange(bx);
int hr[4], lr[4], fr[4];
meow_widget_rect(header, hr);
meow_widget_rect(list, lr);
meow_widget_rect(footer, fr);
printf("DEMO layout: header(%d,%d,%d,%d) list(%d,%d,%d,%d) footer(%d,%d,%d,%d)\n",
hr[0], hr[1], hr[2], hr[3], lr[0], lr[1], lr[2], lr[3], fr[0], fr[1], fr[2], fr[3]);
meow_widget_draw(header);
meow_widget_draw(list);
meow_widget_draw(footer);
meow_ui_flush(); /* 上屏并 MEOW_UI_DUMP 写 PPM *//* (host 离屏无 fb → 只落盘) */
/* ---- fling:对列表做一次惯性下滑(速度跟踪→减速→停)---- */
meow_scroll *s = meow_scroll_wrap(list, 0);
int maxs = meow_list_max_scroll(list);
uint64_t t = meow_ui_time_ms();
for (int i = 0; i < 14; i++) meow_scroll_track(s, 40, t + (uint64_t)i * 16);
meow_scroll_fling(s);
int guard = 0;
while (meow_scroll_active(s) && guard++ < 300) { meow_anim_tick(); usleep(10000); }
meow_anim_tick();
int end = meow_scroll_offset(s);
printf("DEMO fling: max_scroll=%d final=%d (active=%d)\n", maxs, end, meow_scroll_active(s));
meow_scroll_free(s);
meow_box_free(bx);
meow_widget_free(list);
meow_widget_free(header);
meow_widget_free(footer);
meow_ui_shutdown();
printf("DEMO OK\n");
return 0;
}