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:
1 parent
553a7d5d9e
commit
5a5e995ebd
19 files changed
+1839
-2
No files matched your search
+127
-1
@@ -1072,7 +1072,133 @@ patch_v2/meow_launcherd/meow_font.a # 复用(静态链接)
|
||||
|
||||
---
|
||||
|
||||
## 12. 遗留 / 待实现
|
||||
## 12. 控件层扩展:可组合布局引擎 / 动画基座 / 滚动物理
|
||||
|
||||
> **性质**:三块**独立增量**(对照 §5.8.5 的「固定尺寸 Row/Column/Box」与 §7 的「B1 最小动画」做升级),
|
||||
> **全部追加式**:新头 `include/meow_ui_box.h` / `include/meow_ui_anim.h` / `include/meow_ui_scroll.h` +
|
||||
> 新 TU `meow_ui_box.c` / `meow_ui_anim.c` / `meow_ui_scroll.c`;**不改任何既有 API 签名/行为**。
|
||||
> 既有控件仍是**绝对定位**(x,y,w,h);布局只是「帮你算坐标」的容器,不改变绘制/命中/状态机。
|
||||
> 旧绝对坐标**永远有效**——不用这三块的 App 完全照旧。
|
||||
|
||||
### 12.1 线性布局引擎(`meow_box`)
|
||||
|
||||
在既有 `meow_row/column/box`(§5.8.5,只支持固定尺寸+居中)之上,提供更完整的线性布局:
|
||||
|
||||
- **容器**:竖直(`MEOW_BOX_V`)/ 水平(`MEOW_BOX_H`)。
|
||||
- **子项尺寸策略**:固定(`MEOW_BOX_FIXED`,取控件当前 w/h)| 权重(`MEOW_BOX_WEIGHT`,均分剩余主轴空间)| wrap(`MEOW_BOX_WRAP`,按内容测量)。
|
||||
- **间距/边距**:容器 `padding`(left/top/right/bottom)+ 项间 `gap`;子项 margin 读取既有 `meow_widget_opts.margin_x/y`。
|
||||
- **主轴对齐**:start / center / end / space-between / space-around / space-evenly。
|
||||
- **交叉轴对齐**:start / center / end / stretch(填满容器交叉向减 margin)。
|
||||
- **嵌套**:box 内可再挂子 box(`meow_box_add_sub`),求解深度 ≤ `MEOW_BOX_MAX_DEPTH`(16,静态栈,无递归爆炸)。
|
||||
|
||||
```c
|
||||
typedef struct meow_box meow_box;
|
||||
typedef enum { MEOW_BOX_H = 0, MEOW_BOX_V = 1 } meow_box_dir;
|
||||
typedef enum { MEOW_BOX_FIXED = 0, MEOW_BOX_WEIGHT = 1, MEOW_BOX_WRAP = 2 } meow_box_size;
|
||||
typedef enum {
|
||||
MEOW_BOX_ALIGN_START = 0, MEOW_BOX_ALIGN_CENTER, MEOW_BOX_ALIGN_END,
|
||||
MEOW_BOX_ALIGN_SPACE_BETWEEN, MEOW_BOX_ALIGN_SPACE_AROUND, MEOW_BOX_ALIGN_SPACE_EVENLY,
|
||||
} meow_box_align;
|
||||
typedef enum { MEOW_BOX_CROSS_START = 0, MEOW_BOX_CROSS_CENTER, MEOW_BOX_CROSS_END, MEOW_BOX_CROSS_STRETCH } meow_box_cross;
|
||||
|
||||
meow_box *meow_box_new(meow_box_dir dir); /* 命名避开既有 meow_box_create(W_LAYOUT) */
|
||||
void meow_box_free(meow_box *b);
|
||||
void meow_box_set_rect(meow_box *b, int x, int y, int w, int h); /* 容器矩形(绝对坐标) */
|
||||
void meow_box_set_padding(meow_box *b, int l, int t, int r, int btm);
|
||||
void meow_box_set_gap(meow_box *b, int gap);
|
||||
void meow_box_set_align(meow_box *b, int main_align, int cross_align);
|
||||
int meow_box_add(meow_box *b, meow_widget *w, int size, int weight); /* 固定/权重 */
|
||||
int meow_box_add_ex(meow_box *b, meow_widget *w, int size, int weight,
|
||||
int min, int preferred, meow_box_measure_fn m, void *mctx); /* WRAP 测量 */
|
||||
int meow_box_add_sub(meow_box *b, meow_box *sub, int size, int weight); /* 嵌套 */
|
||||
|
||||
/* 单遍求解:把每个子控件 x/y/w/h 写进 meow_widget(新增 meow_widget_set_rect);深度≤16 静态栈。
|
||||
* 子控件 margin(widget opts.margin_x/y)参与排布;嵌套 sub 递归。 */
|
||||
void meow_box_arrange(meow_box *b);
|
||||
```
|
||||
|
||||
- **与视图框架集成(opt-in)**:box 可作 `meow_view` 的布局提供者;view **不设**就保持现有绝对坐标行为。
|
||||
`meow_view_set_layout(v, box)` 登记 + 立即排一次;`meow_view_relayout(v)` 手动重排;
|
||||
顶层页在 `meow_view_page_push/pop/replace` 进入时自动重排。box 矩形默认跟 view 内容矩形(w/h 未设时自动填)。
|
||||
```c
|
||||
void meow_view_set_layout(meow_view *v, meow_box *box); /* NULL=取消 */
|
||||
void meow_view_relayout(meow_view *v);
|
||||
```
|
||||
- **控件尺寸测量**:`MEOW_BOX_FIXED`/`WRAP`(无 measure 回调)直接取控件当前 `w/h`(对既有固定尺寸控件天然兼容);
|
||||
`WRAP` 可用 `meow_box_measure_fn`(给出主轴向 min/preferred)供内容自适应的自定义控件用。
|
||||
- **内存纪律**:box 静态池、定长子项数组(`MEOW_BOX_MAX_CHILD=24`),arrange 热路径零 malloc;嵌套用深度≤16 静态栈。
|
||||
|
||||
### 12.2 动画基座 + UI 节拍器(`meow_anim` / `meow_anim_tick`)
|
||||
|
||||
把 §7「应用在 on_tick 里用 `meow_ui_time_ms` 做时间轴」收敛成**声明式 tween**:
|
||||
|
||||
- **缓动**:linear / ease-out / ease-in-out / overshoot(`meow_ease_apply`)。
|
||||
- **动画对象**:`meow_anim_start` 一次性声明 from/to/duration/easing + `update`(每帧插值回调)+ `done`(完成/取消回调);**并行多动画**(静态池 ≤ `MEOW_ANIM_MAX=16`)、**取消**(`meow_anim_cancel`)。
|
||||
- **节拍**:`meow_anim_tick()` 挂既有 `meow_ui_run` 主循环(on_tick 之后)自动调用;**无动画时零开销**(只查计数即返回),不引入常驻高频轮询。阻塞 IME 循环(`meow_ui_feed_tick`)不喂 tick(动画在模态期暂停)。
|
||||
- **与脏区集成**:`meow_anim_set_region(a,x,y,w,h)` 让每帧**只 flush 动画影响区**,不做整屏重绘;app 的 `update` 回调也可自行 `meow_ui_flush_region`。
|
||||
|
||||
```c
|
||||
typedef enum { MEOW_EASE_LINEAR = 0, MEOW_EASE_OUT, MEOW_EASE_IN_OUT, MEOW_EASE_OVERSHOOT } meow_ease;
|
||||
float meow_ease_apply(meow_ease e, float t); /* t∈[0,1]→[0,1];overshoot 中后段可略>1、末点=1 */
|
||||
|
||||
typedef struct meow_anim meow_anim;
|
||||
typedef void (*meow_anim_update_fn)(meow_anim *a, float v, void *ctx);
|
||||
typedef void (*meow_anim_done_fn)(meow_anim *a, int canceled, void *ctx);
|
||||
typedef struct meow_anim_desc {
|
||||
float from, to; uint32_t duration_ms; meow_ease ease;
|
||||
meow_anim_update_fn update; meow_anim_done_fn done; void *ctx;
|
||||
} meow_anim_desc;
|
||||
|
||||
meow_anim *meow_anim_start(const meow_anim_desc *d);
|
||||
void meow_anim_cancel(meow_anim *a);
|
||||
int meow_anim_active(meow_anim *a);
|
||||
float meow_anim_value(meow_anim *a);
|
||||
void meow_anim_set_region(meow_anim *a, int x, int y, int w, int h);
|
||||
void meow_anim_tick(void); /* 推进所有活动动画(挂主循环;无动画零开销) */
|
||||
unsigned meow_anim_count(void);
|
||||
```
|
||||
|
||||
- **与 §7 的关系**:§7(B1 最小可用)是手写时间轴;本模块是正式基座。应用可任选其一或混用。
|
||||
- **内存纪律**:静态池 ≤16,start/cancel/tick 全程零 malloc。
|
||||
|
||||
### 12.3 滚动物理(`meow_scroll`)
|
||||
|
||||
给既有滚动容器(`meow_list` / `W_LIST` lazycolumn/lazyrow / `meow_listview`)加**可惯性滚动**物理层:
|
||||
|
||||
- **速度跟踪**:`meow_scroll_track(dy, t)`(拖动跟手 + 采样),fling 时用**最近 N 个采样加权**得初速。
|
||||
- **松手 fling**:`meow_scroll_fling(s)` 起一条减速度曲线动画(用 §12.2 动画基座驱动)推进位移;每帧**只 redraw 列表视口区**(不整屏)。
|
||||
- **边界过冲 clamp + 简单回弹**:free 目标越界 → clamp 到 `[0,max]`;快速撞墙补两段短 IN_OUT 回弹(不做复杂 spring)。
|
||||
- **滚动停止自动归位**:`meow_scroll_set_snap(step)` 可选吸附到 step 倍数。
|
||||
- **跟手拖动行为保持现状不变**:`track` 内部调既有 `meow_list(viewport)_set_scroll`(clamp 一致),与 app 直接 `scroll_by` 等价;app 把拖动的 `scroll_by` 换成 `track` 即可获得速度采样。
|
||||
|
||||
```c
|
||||
typedef struct meow_scroll meow_scroll;
|
||||
meow_scroll *meow_scroll_create(meow_scroll_set_fn set, meow_scroll_max_fn max,
|
||||
meow_scroll_get_fn get, meow_scroll_redraw_fn redraw, void *ctx);
|
||||
meow_scroll *meow_scroll_wrap(meow_widget *list, int is_listview); /* 1=W_LISTVIEW / 0=W_LIST 或 lazycolumn/row */
|
||||
void meow_scroll_free(meow_scroll *s);
|
||||
void meow_scroll_track(meow_scroll *s, int dy, uint64_t t_ms); /* 跟手拖动 + 速度采样 */
|
||||
void meow_scroll_fling(meow_scroll *s); /* 松手惯性滑动(内部算初速) */
|
||||
void meow_scroll_stop(meow_scroll *s); /* 立即停止 */
|
||||
int meow_scroll_velocity(meow_scroll *s); /* 加权初速 px/s */
|
||||
int meow_scroll_active(meow_scroll *s);
|
||||
int meow_scroll_offset(meow_scroll *s);
|
||||
void meow_scroll_set_snap(meow_scroll *s, int step);
|
||||
void meow_scroll_set_friction(meow_scroll *s, int tau_ms); /* 默认 180ms */
|
||||
```
|
||||
|
||||
- **内存纪律**:静态池(应用侧按需建会话),track/fling/tick 全程零 malloc;无 fling 时 meow_scroll 不参与节拍(由 `meow_anim_tick` 活动计数保证零开销)。**不引 libm**(SDK 免 `-lm` 约定)。
|
||||
|
||||
### 12.4 对既有 App 的零影响(迁移说明)
|
||||
|
||||
- **追加式**:三块全为新 API;既有 `meow_row/column/box`(§5.8.5)与全部 `meow_*_create/hit/scroll` 签名一行未改。
|
||||
- **旧绝对坐标永远有效**:box 只是把坐标算进 `meow_widget`(`meow_widget_set_rect`);不用 box 的 App 照旧 `on_layout`/绝对定位。
|
||||
- **机制层新增**:`meow_ui_input.c` 主循环新增 `meow_anim_tick()` 调用(无动画零开销);`meow_ui_view.c` 新增布局登记表(未设布局的 view 行为不变);`meow_ui_widget.c` 新增 `meow_widget_set_rect`(只设字段不标脏,既有 `meow_layout_arrange` 不受影响)。
|
||||
- **同步重编注意**:`meow_ui.a` 内容变化(新增 box/anim/scroll 三个 `.o`,`meow_ui_widget.o`/`meow_ui_view.o`/`meow_ui_input.o` 重编)→ 链 `meow_ui.a` 的 App 需**重链**(`build_sdk.sh` 一键重编 + 各 App `build_*.sh` 重链)。既有 App **不改源码**即可零回归。
|
||||
|
||||
---
|
||||
|
||||
## 13. 遗留 / 待实现
|
||||
|
||||
1. `meow_ui` 渲染后端需从 launcher 里**抽公共绘制实现**(`back_buf`/`meow_dirty_*`/`meow_present`/`meow_font_bind` 目前是 launcher 静态函数——需提取为可链接的 `meow_ui_gfx` 或改为共享 obj,注意 launcher 与 app 是**不同进程**,不能共享同一 back_buf;`meow_ui.a` 是**独立库**,内部自建 fb 上下文,不复用 launcher 的全局 `g_dirty`)。
|
||||
2. 输入线程优先级:vs 主循环 10ms 热键轮询的竞态,需在 B1 实现时定义清楚(应用进程内独立事件循环,不与 launcher 抢)。
|
||||
|
||||
Reference in new issue
Block a user