M2.60→M2.61 骨架: SDK Activity 栈 + 控件归属(agent-122) + 按钮去圈/即时重绘(agent-119) + SDK 模板文档(agent-121)
- SDK §6.1 三层控件模型: Activity栈(push/pop/active) + 页面控件归属 owner + meow_ui_global_* 骨架(②) + 系统级仅内部接口(③) - meow_widget 加 owner; live_btn_hit/meow_widget_hit 仅 active activity 命中; touch_refresh stale 保护 - 根治"全屏页触摸主页按钮闪现"(跨页面控件残留); 控件对象复用弹栈不重建 - hello 迁移双 Activity(home/full): 全屏左滑=弹栈回主页, 根左滑=退出 - agent-119 按钮去圈(纯色accent+黑12/24%)+即时局部重绘保留; agent-121 SDK模板§5.3-5.7
This commit is contained in:
1 parent
07c556e907
commit
6824defdf9
13 files changed
+613
-23
No files matched your search
+314
@@ -202,6 +202,270 @@ const char *meow_ime_text(void);
|
||||
|
||||
---
|
||||
|
||||
### 5.2 横向分页(横向滑动切换页面)设计模板 [源:2026-08-30]
|
||||
|
||||
> **性质**:SDK 设计模板,供后续 APP 主页/子页**按需选用**;参照 HibyOS 播放器主页横划进播放页的实现思路。**B1 不实现**,本小节只列设计要点与接口草案(标注「草案/待定案」),供后续落地时对齐,避免与既有手势/控件约定冲突。
|
||||
|
||||
**模板目标**:多页横向滑动切换,流畅不卡;供 APP 主页/子页复用。
|
||||
|
||||
**1) 手势分流(关键,与既有手势不冲突)**:按**起始位置**分流,三者互斥——
|
||||
- 触点落在**屏幕左缘(≤24px)热区** → SDK **左滑返回**(不动画,`on_swipe(LEFT)`,见 §6 与 spec-ref §5.1)。
|
||||
- 触点落在**中部**左/右滑 → **页切换**(页视图接管)。
|
||||
- **顶部**下滑 → **通知中心**(不夺走既有顶部热区)。
|
||||
> 命中判定:先判断按下 x 落在左缘/顶部热区还是中部,再定手势语义;互斥,不与既有「左缘返回 + 顶部下滑通知中心」冲突。
|
||||
|
||||
**2) 预渲染快照缓存(抗卡顿核心)**:
|
||||
- 相邻页各预渲染一张 `back_buf` 快照(页小数据 + 内容缓存)。切换时**只 blit 快照**,**不重跑布局/控件绘制**(页多不卡的关键)。
|
||||
- 缓存上限 = 当前页前后各 1 页(共 3 张 ≈ 3 × 屏宽 × 高 × 2B;480×720 RGB565 每张 ≈ 0.66MB → 3 张约 2MB,远低于 14MB 内存预算;按更保守 2MB/张 × 3 ≈ 6MB 口径亦可接受)。
|
||||
- **LRU 淘汰**远页;回滚重建时显示「加载中」轻提示。
|
||||
|
||||
**3) 拖动 / 吸附**:
|
||||
- 手指**跟手平移当前页 + 露出下一页边缘**:单帧内多次 blit 位移 + **一次** `meow_present`(vsync 门控 ≤60 帧,**不做逐帧重排版**)。
|
||||
- 松手**过阈值** → 补 2-4 帧平移动画**吸附相邻页**;**未过阈值** → 回弹当前页;**首/末页**不滑(或橡皮筋回弹)。
|
||||
|
||||
**4) 性能要点**:切换 = 快照 blit + 位移平移(**内存拷贝远快于重绘**) + 节流 present;拖动时**零 UI 重算**(不触发布局/控件重绘)→ 页多不卡。
|
||||
|
||||
**5) SDK 建议 API 草案(「草案/待定案」,不实现)**:
|
||||
```c
|
||||
typedef struct meow_page_view meow_page_view;
|
||||
|
||||
/* 数据源回调:页数 / 每页渲染回调 */
|
||||
typedef struct {
|
||||
int (*page_count)(void *ctx); /* 总页数 */
|
||||
void (*draw_page)(meow_page_view *pv, int page,
|
||||
uint16_t *snapshot, void *ctx); /* 渲染该页到快照 buf */
|
||||
void *ctx;
|
||||
} meow_page_view_source;
|
||||
|
||||
meow_page_view *meow_page_view_create(const meow_page_view_source *src,
|
||||
int x, int y, int w, int h);
|
||||
void meow_page_view_free(meow_page_view *pv);
|
||||
int meow_page_view_set(meow_page_view *pv, int page); /* 跳页(快照重建 + 吸附动画) */
|
||||
int meow_page_view_current(const meow_page_view *pv); /* 当前页 */
|
||||
```
|
||||
> SDK **内部**处理:手势分流(**左缘返回除外**,仍归 SDK 手势层 `on_swipe(LEFT)`)、快照缓存、平移吸附、LRU 淘汰、加载中提示。实现时以 `meow_ui.h` 为准。
|
||||
|
||||
**6) 关联**:与既有「**全局左缘返回 + 顶部滑条 + 状态栏收合/通知中心**」手势约定一致(spec-ref §5.1/§3.1)——左缘返回仍为全局手势(`on_swipe(LEFT)`/`on_swipe_progress`);页视图**只接管中部横滑**;顶部下滑仍归通知中心。三者按起始位置分流,互斥不冲突。
|
||||
|
||||
### 5.3 SDK 可复用设计模板清单 [源:2026-08-30]
|
||||
|
||||
> **性质**:把 MeowOS 应用开发里反复出现的**界面结构**抽象为可复用的设计模板(设计要点 + 交互约定 + 绘制/数据模型 + 性能注意 + 复用组合),供各 App 与设置页按需选用、观感统一。**本小节是目录**:列出全部模板及优先级/状态;已展开为设计模板者见对应小节。**所有模板与既有手势/控件约定一致**(见 §5.2/§6/spec-ref §5.1/§3.1),且相互可组合。
|
||||
|
||||
| # | 类别 | 模板 | 一句用途 | 优先级/状态 |
|
||||
|---|------|------|---------|------------|
|
||||
| ① | A | 分组设置表单 | 分组标题 + 行(开关/滑条/下拉/子菜单/信息),数据源 = setting 键 | ✅ **A+B 先行**(已展开 §5.4) |
|
||||
| ② | A | 列表+选择 | 行数据源回调(图标+标题+副标题+右侧操作),滚动/单选/多选/搜索 | ✅ **A+B 先行**(已展开 §5.5) |
|
||||
| ③ | B | 弹窗/对话框 | 确认/选择/输入/信息,模态/非模态,返回/电源键关闭 | ✅ **A+B 先行**(已展开 §5.6) |
|
||||
| ④ | B | 顶/底部下拉面板 | 快捷设置/通知中心/侧边栏,收合动画、内容懒载 | ✅ **A+B 先行**(已展开 §5.7) |
|
||||
| ⑤ | C | 媒体控制/播放页 | 进度/控制/封面/歌词滚动 | 🔵 随播放器 app 细化 |
|
||||
| ⑥ | C | 沉浸内容页 | 全屏/左滑返回/图片缩放/歌词随乐 | 🔵 随播放器 app 细化 |
|
||||
| ⑦ | C | 进度/加载 | 进度条/转圈/骨架屏/下拉刷新 | 🔵 随对应 app 细化 |
|
||||
| ⑧ | D | 卡片/磁贴 | 圆角卡片/图标宫格/应用网格 | 🔵 随 MD3 细化 |
|
||||
| ⑨ | D | 导航栏/工具栏 | 顶标题+返回/底栏 tabs/面包屑 | 🔵 随导航细化 |
|
||||
| ⑩ | D | 列表项布局 | 图标+文本+右侧操作,点击/长按/滑删 | 🔵 随 MD3 细化 |
|
||||
| ⑪ | E | 拖拽排序/长按菜单/时间轴 | 拖拽排序/长按菜单/时间轴 | ⚪ **E 后置(可选)** |
|
||||
|
||||
**优先级 / 状态说明**:
|
||||
- **A+B 先行(近期展开,§5.4-§5.7)**:设置表单/列表/弹窗/面板是现阶段 MeowOS 应用(设置、通知、App 列表、WiFi)最常用的四类结构,先定下来沉淀范型,落地时可复用 launcher 已调通的 `s_row_*`/`s_dd_modal` 逻辑。
|
||||
- **C-D 随对应 app/MD3 细化**:媒体/沉浸/加载随播放器类 app 落地时细化;卡片/导航/列表项随 MD3 观感统一时细化——避免过早抽象、先让 app 跑通。
|
||||
- **E 后置**:拖拽排序/长按菜单/时间轴为可选增强,非首批通用结构,后续需要时再立项。
|
||||
- **已含横向分页**:多页横向滑动已在 §5.2 单独展开,**不重复**列入本清单。
|
||||
- **可扩展**:本清单按需增项(新模板补一行;若展开则新增一节),编号后续连续。
|
||||
|
||||
> **手势一致性(此处只述结论,不重复展开)**:全部模板与既有「**全局左缘返回 + 顶部滑条 + 状态栏收合 + 通知中心热区**」手势约定一致(spec-ref §5.1/§3.1、本文件 §5.2/§6)——左缘 ≤24px 内划≥90px 抬手=返回(`on_swipe(LEFT)`/`on_swipe_progress`);顶部下滑=通知中心;**中部**横滑/竖滑才归内容。各模板**不重定义**这些全局手势,只在其上做内部命中分流。
|
||||
|
||||
---
|
||||
|
||||
### 5.4 设计模板 A① 分组设置表单 [源:2026-08-30]
|
||||
|
||||
> **参照**:`patch_v2/meow_launcherd/meow_launcherd.c` 设置页(`SMENU` 表 + `srow_t` + `draw_settings_page`/`run_settings_page`)。**性质**:SDK 设计模板,供 App/设置页按需选用;`meow_ui.h` 现状控件最小集(按钮/滑条/开关/列表,§5)只提供单控件,本模板是把它们**组织成「分组设置表单」的结构范型**。API 为「草案/待定案」,不实现。
|
||||
|
||||
**摘要**:一页设置表单 = 若干**分组标题行** + 若干**设置行**。每行 `label + 控件`,控件类型决定取值方式——开关 / 滑条 / 下拉(枚举·预设)/ 子菜单 / 信息 / 列表。数据源 = **setting 键**(经 `meow_settings_*` 读写,见 spec-ref §4),UI 只绑定键、不直接触存储文件。
|
||||
|
||||
**关键交互**:
|
||||
- **分组标题行**(`key=NULL`)仅展示分组名(如「显示/网络/电源/字体主题」),不可选中。
|
||||
- **行命中分发**:触摸命中某行后按行控件类型分发——
|
||||
- **开关**:`meow_settings_set_switch(key, !on)`(或 `set_bool`),行右侧画开关。
|
||||
- **滑条**:按下/拖动沿 track 取值 → `meow_settings_set_int(key, v)`(后台 clamp 到 min..max + 同步缓存),行内画 track+thumb+当前值。
|
||||
- **下拉(枚举/预设)**:点行 → 弹**单选**弹窗(复用 B③ §5.6)→ `meow_settings_set_enum/set_str(key, idx)`。
|
||||
- **子菜单**(如字体 family→weight 两级):点行 → 二级列表(复用 A② §5.5 容器)→ 选中写回串值(如卡根相对路径 `MeowOS/fonts/<family>/<weight>/font.png`)。
|
||||
- **信息/列表**:点行 → 打开只读详情或子列表(如「关于本机」「WiFi 连接状态」「附近WiFi」)。
|
||||
- **滚动**:整行步进(`SROW_H`),选中行钳制在视口内;列表拖动滚动(纵向位移超阈值判滚动、非 tap)。
|
||||
- **返回/取消**:左缘返回手势回上级(全局手势,不由本模板重定义)。
|
||||
|
||||
**绘制/数据模型**:
|
||||
- **行描述结构**(参照 `srow_t`):`{label, key, ctrl(min,max,step), presets/preset_labels/preset_n, net_list}`;`ctrl ∈ {HEADER, SWITCH, SLIDER, ENUM, PRESET, INFO, LIST}`;`key=NULL` 表示分组标题行。
|
||||
- **单卡片 + 固定行高**:`SET_CARD_X/W/Y/H` + `SROW_H`(行高统一,便于整行滚动对位与裁剪;视口高取行高的整数倍)。
|
||||
- **可见性**:`s_row_visible(i)`(如多字体 6 个 class 行仅在开关开时可见)→ 压缩索引 `s_vis_of/vis_at`;标题行恒显。
|
||||
- **值格式化**:`s_fmt_*`(秒→「×分×秒」、分钟→「HH:MM」、枚举→中文标签、预设项显示名)。
|
||||
- **命中/滚动换算**:`s_row_at_content_y(cy)`(content 坐标→行号);滑条单独记录 track 纵坐标供拖动命中。
|
||||
|
||||
**性能注意**:
|
||||
- **局部刷新**:静态展示不主动刷新,仅在交互时经 `meow_dirty` 区标脏 + `meow_ui_flush_region` 只刷变化区(滑条拖动/开关切换/选中行高亮)。
|
||||
- 滑条拖动**实时** `set_int`(后台 clamp、同步缓存,不逐 1% 落盘),松手才落盘;避免拖动时每帧写文件。
|
||||
- 滚动用整行步进 + 区间钳制,不做逐像素重排。
|
||||
|
||||
**复用组合**:A① 是容器;行内容用 A②(列表项布局)/ B③(下拉弹窗)+ SDK 控件(`meow_btn/slider/switch`);设置页顶部「快捷开关」组可再被 B④ 面板复用。
|
||||
|
||||
**API 草案(「草案/待定案」,不实现;实现以 `meow_ui.h` 为准)**:
|
||||
```c
|
||||
typedef enum { MEOW_FROW_HDR, MEOW_FROW_SWITCH, MEOW_FROW_SLIDER,
|
||||
MEOW_FROW_ENUM, MEOW_FROW_PRESET, MEOW_FROW_INFO,
|
||||
MEOW_FROW_LIST } meow_frow_type_t;
|
||||
typedef struct {
|
||||
const char *label;
|
||||
const char *key; /* setting 键,经 meow_settings_* 读写;NULL=分组标题行 */
|
||||
meow_frow_type_t ctrl; /* 控件类型 */
|
||||
int min, max, step; /* SLIDER 取值域/步进 */
|
||||
} meow_frow_t;
|
||||
meow_widget *meow_ui_setform_create(const meow_frow_t *rows, int n, int x, int y, int w, int h);
|
||||
int meow_ui_setform_sel(meow_widget *f); /* 当前选中行 */
|
||||
void meow_ui_setform_scroll(meow_widget *f, int offset); /* 整行步进滚动 */
|
||||
int meow_ui_setform_hit_row(meow_widget *f, int x, int y);/* 命中行号(-1=分组标题/卡片外) */
|
||||
```
|
||||
> 说明:`meow_ui_setform_*` 与 launcher 的 `srow_t`/`SMENU`/`run_settings_page` 同构(一行=label+key+控件),实现期可直接借已调通逻辑。**区分「行描述表」与「每行当前值」**——值一律经 `meow_settings_get_*` 读取,不缓存在行结构里(避免双写漂移)。
|
||||
|
||||
---
|
||||
|
||||
### 5.5 设计模板 A② 列表+选择 [源:2026-08-30]
|
||||
|
||||
> **性质**:SDK 设计模板,供 App 主页/子页按需选用;对既有 `meow_list_create`(B1 最小集,§5,仅 label 文本)做**结构化扩展**(行=图标+标题+副标题+右侧操作 + 选中态)。API「草案/待定案」,不实现。
|
||||
|
||||
**摘要**:可滚动选择容器。**行数据源回调**逐行给出(图标 / 标题 / 副标题 / 右侧操作 / 是否可选),容器负责绘制/滚动/选中/命中;支持**单选、多选、长按**(上下文操作)。适合「已保存网络 / 附近WiFi / 蓝牙设备 / 歌曲列表 / 设置子菜单」等。
|
||||
|
||||
**关键交互**:
|
||||
- **行内容**:图标(可选 `meow_img*` 或内置符号)+ 标题 + 副标题(次要信息,如 SSID/设备名/时长)+ **右侧操作**(如箭头/开关/详情钮)。点整行=选中/进入;点右侧操作=该行动作。
|
||||
- **单选/多选**:`mode` 决定——单选(高亮当前 + 确认回填);多选(复选标记);「无选择」= 纯入口列表。
|
||||
- **长按**:长按行 → 上下文菜单(如删除/重命名),或不弹菜单仅标记长按态(复用 B③ 小弹窗)。
|
||||
- **搜索/过滤**:顶部搜索框(IME 输入,§5.1)→ 数据源回调按关键字过滤重算行数(B1 IME 仅英文/数字)。
|
||||
- **滚动**:局部 dirty;整行步进或像素滚动均可;首/末行钳制(橡皮筋或截断)。
|
||||
|
||||
**绘制/数据模型**:
|
||||
- **行数据源回调**(`meow_list_source` 的结构化扩展):
|
||||
```c
|
||||
typedef struct {
|
||||
const meow_img *icon; /* 可选 */
|
||||
const char *title; /* 主文本 */
|
||||
const char *subtitle; /* 副文本,可空 */
|
||||
int right; /* 右侧操作类型(无/箭头/开关/详情钮) */
|
||||
int enabled; /* 可选中性 */
|
||||
} meow_list_item;
|
||||
typedef int (*meow_list2_source)(int idx, meow_list_item *out, void *ctx); /* 返回 1=有该项,0=越界 */
|
||||
```
|
||||
- **容器**:视口(x,y,w,h) + 总行数(count,可再查询更新) + 滚动偏移;`count` 由数据源动态变化(搜索过滤/懒加载)。
|
||||
- **命中**:行 = `y/row_h`;**右侧操作细分命中**(行右侧 1/3 区域判操作,其余判整行)。命中判定避免 goodix 时序问题——**按下不锁原点**、抬手时用最新有效坐标(参照 §5.6 与 meow_touch 语义)。
|
||||
- **选中态**:单选高亮条 / 多选复选标记,用主题 accent 色。
|
||||
|
||||
**性能注意**:
|
||||
- **局部 dirty**:滚动/翻页只刷变化行(`meow_ui_flush_region` 行块或视口带),不整屏重绘;数据源回调每行**轻量填充**,不在回调里做 IO(大图标用缓存/延迟加载)。
|
||||
- **懒加载**:行多(如几百首歌曲)时数据源按需返回,仅落入视口 ± 预取若干行才真正加载。
|
||||
- **内存**:行数据瞬时(回调填充到栈上 `meow_list_item`),不长期持有全部行对象;图标句柄归属调用方。
|
||||
|
||||
**复用组合**:A② 是 A① 的子菜单/列表行、B③ 的「选择」数据源、播放页歌单的通用底座;选中结果回填到 A① 的下拉项。
|
||||
|
||||
**API 草案(「草案/待定案」,不实现;实现以 `meow_ui.h` 为准)**:
|
||||
```c
|
||||
typedef enum { MEOW_LIST_SEL_NONE, MEOW_LIST_SEL_SINGLE, MEOW_LIST_SEL_MULTI } meow_list_sel;
|
||||
typedef int (*meow_list2_source)(int idx, meow_list_item *out, void *ctx);
|
||||
meow_widget *meow_ui_listview_create(int x, int y, int w, int h, int count,
|
||||
meow_list2_source src, void *ctx, meow_list_sel mode);
|
||||
void meow_ui_listview_set_sel(meow_widget *lv, int idx); /* 单选/多选当前选中集 */
|
||||
int meow_ui_listview_get_sel(meow_widget *lv, int *out, int max);
|
||||
void meow_ui_listview_scroll(meow_widget *lv, int offset);
|
||||
int meow_ui_listview_hit(meow_widget *lv, int x, int y); /* 命中行;右侧操作另判 */
|
||||
```
|
||||
> 说明:既有 `meow_list_create`(label-only)保留;`meow_ui_listview_*` 为**结构化扩展**(图标/副标题/右侧/选中),可作为真则替换裸 label 列表。
|
||||
|
||||
---
|
||||
|
||||
### 5.6 设计模板 B③ 弹窗/对话框 [源:2026-08-30]
|
||||
|
||||
> **参照**:`meow_launcherd.c` `s_dd_modal()`(WiFi 列表 / 关于本机 / 字体子菜单共用同一模态)。**性质**:SDK 设计模板,覆盖 **确认/选择/输入/信息** 四种;模态/非模态;返回/电源键关闭;遮罩。`meow_ui.h` 无通用弹窗,本模板为「草案/待定案」。
|
||||
|
||||
**摘要**:在应用之上弹出**居中卡片**(遮罩压暗 + 圆角卡片 + 标题 + 内容 + 操作),用于打断当前流程的一次性决策。按用途分四型:确认(是/否)、选择(单选列表,可复用 A② 数据源)、输入(复用 IME §5.1)、信息(只读展示,如「关于本机」)。
|
||||
|
||||
**关键交互**:
|
||||
- **模态 vs 非模态**:模态=遮罩吞掉背景输入、打开期间应用主界面不可交互(返回/电源关闭);非模态=不遮罩、可同时操作背景(如播放页浮层)。默认模态。
|
||||
- **关闭途径**:① 点操作钮确认/取消;② 点遮罩外=取消;③ 返回键(左缘返回手势 / 虚拟返回键)→ 取消;④ **电源键单击** → 确认当前高亮项(launcher `s_dd_modal` 的电源抬起=确认语义)。音量键上下移动高亮。
|
||||
- **选择弹窗**:选项列表高亮 + 预勾选(`cur` 非 -1 时);`cur=-1` = 只读展示不预选(「关于本机」)。
|
||||
- **物理键可访问**:音量=移动高亮、电源=确认、返回=取消(借鉴 `s_dd_modal` 的 `kp_*` 键轮询)。
|
||||
|
||||
**绘制/数据模型**:
|
||||
- **绘制**(参照 `s_dd_modal`,即画即显一次成型):
|
||||
1. 全屏遮罩 `meow_ui_fill_rect_alpha(0,0,W,H, 0x000000, 150)`(压暗)。
|
||||
2. 居中卡片 `meow_gfx_fill_round(d_x,d_y,d_w,d_h, 16, surface_container)` + `meow_ui_draw_rect_round(..., 16, outline)` 描边;圆角 16。
|
||||
3. 标题(theme `on_surface`,20 号)+ 选项行(行高 ~48;选中行 `primary` α36 高亮 + 白字;预勾选项右侧画小方块)。
|
||||
4. **不压状态栏**:卡片 y 钳制 `d_y ≥ meow_ui_statusbar_height()`;底部留 ≥20px。
|
||||
- **尺寸**:宽 ~348、居中;高 = 标题 + n×行高 + 内边距;内容过多滚动(或扩容)。
|
||||
- **数据模型**:`{title, item[], n, cur, type}`;选择型=选项数组;信息型=多行文本;输入型=携 IME ctx。
|
||||
- **命中**:抬手时用**最新有效坐标**(不锁按下原点,goodix 免疫);卡片内命中→选项;卡片外→取消。打开前**双排空触摸残留**(`s_dd_modal` 的 open 后 read 排空→40ms→再排空,吸收 goodix 抬起长尾)。
|
||||
|
||||
**性能注意**:
|
||||
- **即画即显**:弹窗打开时**一次性**画好遮罩+卡片+选项,再进事件循环(`s_dd_modal` 初始绘制一次,仅高亮变化才重绘);不每帧重画静态内容。
|
||||
- 重绘只刷变化区(切换选中高亮时,仅重画遮罩+卡片或行块 `flush_region`)。
|
||||
- 无动画(B1 无 tween);如需淡入淡出,用 `fill_rect_alpha` 单次叠加以免每帧重算。
|
||||
|
||||
**复用组合**:B③ 是 A① 下拉(enum/preset 选中)、A② 长按上下文菜单、B④ 面板关闭确认、电源菜单的**通用弹窗底座**;输入型接 IME §5.1;选择型数据源同 A②。
|
||||
|
||||
**API 草案(「草案/待定案」,不实现;实现以 `meow_ui.h` 为准)**:
|
||||
```c
|
||||
typedef enum { MEOW_DLG_CONFIRM, MEOW_DLG_SELECT, MEOW_DLG_INPUT, MEOW_DLG_INFO } meow_dlg_t;
|
||||
typedef struct meow_dialog meow_dialog;
|
||||
meow_dialog *meow_ui_dialog_create(meow_dlg_t t, const char *title);
|
||||
void meow_ui_dialog_set_items(meow_dialog *d, const char *const *item, int n, int cur);
|
||||
void meow_ui_dialog_set_ime(meow_dialog *d, meow_ime_ctx *ime); /* INPUT 型 */
|
||||
void meow_ui_dialog_show(meow_dialog *d); /* 阻塞到确认/取消 */
|
||||
int meow_ui_dialog_result(meow_dialog *d); /* 选中=选项下标;输入=IME buf;确认=1/0 */
|
||||
void meow_ui_dialog_close(meow_dialog *d);
|
||||
```
|
||||
> 说明:模态=默认;非模态=`show` 非阻塞变体(启动后由 `on_tick` 驱动)。返回/电源关闭语义**沿用全局约定**(返回=取消;电源=确认当前高亮),本模板不重定义。
|
||||
|
||||
---
|
||||
|
||||
### 5.7 设计模板 B④ 顶/底部下拉面板 [源:2026-08-30]
|
||||
|
||||
> **性质**:SDK 设计模板,覆盖**顶部下拉**(快捷设置/通知中心)与**底部面板**(操作抽屉/侧边栏),带**收合动画**与**内容懒载**。**关键前提**:与既有「全局左缘返回 + 顶部滑条 + 状态栏收合 + 通知中心热区」手势一致(spec-ref §5.1/§3.1、A-13)——本模板**不夺走**「顶部下滑=通知中心」,而是**按起始位置/触达途径与既有热区分流**。API「草案/待定案」。
|
||||
|
||||
**摘要**:沿某种边缘滑出/推入的**非全屏浮层**。顶/底部下拉面板 = 手指从对应边缘向内滑 → 面板从边缘滑出(带收合动画),内容按需加载。典型:快捷设置(亮度/音量/开关)、通知中心(列表)、底部操作抽屉;可再收合。
|
||||
|
||||
**关键交互**:
|
||||
- **手势分流(互斥,与既有约定一致)**:
|
||||
- **左缘 ≤24px 向内划** → **全局左缘返回**(`on_swipe(LEFT)`,SDK 兜底;本面板**不**接管)。
|
||||
- **顶部边缘下滑** → **通知中心**(既有热区,`on_swipe(DOWN)`/顶部热区;全屏下热区缩小但仍保留,见 spec-ref §5.1/A-13)。
|
||||
- **底部边缘上滑** → **底部面板**(本模板新增;底部边缘无既有冲突)。
|
||||
- **快捷设置**:为不与通知中心冲突,**待定案**——建议从通知中心二级拉出、或屏幕右上角/右侧缘单独热区触达、或「通知中心内点箭头展开」。**不新占顶部下滑**(避免与 §5.1 冲突)。
|
||||
- **侧边栏**(可选):右缘向左滑出(右侧无既有手势,安全)。
|
||||
- **收合动画**:跟手平移面板(手指拖多长露多长),松手**过半阈值** → 补 2-4 帧**短插值**吸附到位;**未过** → 回弹。动画只在松手时做一次,不做逐帧几何重算(B1 无 tween;短插值=有限帧序列)。
|
||||
- **内容懒载**:面板**首次拉出**才构建内容(或预建空容器),避免打开即全量绘制;面板内滚动局部 dirty。
|
||||
- **关闭**:点面板外关闭 / 再划回边缘收合 / 返回键关闭(模态时)。
|
||||
|
||||
**绘制/数据模型**:
|
||||
- 面板 = 一个**矩形区域**(顶/底边缘滑出),内容区 + 头部(把手/标题/关闭钮)。绘制走 back_buf,`meow_ui_flush_region` 只刷面板交汇区。
|
||||
- **内容**:快捷设置=一组开关/滑条(复用 A① 控件);通知中心=列表(复用 A②);操作抽屉=一组按钮(复用 `meow_btn`)。
|
||||
- **数据模型**:`{edge, x, y, w, h, content_widget, collapsed, anim_t}`;内容视图句柄(可为 A①② 或自定义);懒载=首次展开时创建内容视图。
|
||||
- **布局 inset**:顶部面板 y 钳制 `≥ meow_ui_statusbar_height()`(非全屏不压状态栏);全屏时顶部热区缩小。
|
||||
|
||||
**性能注意**:
|
||||
- **内容懒载**:展开才构建;收合后保留视图(缓存)或销毁(按需)。
|
||||
- **收合动画**:短插值(≤4 帧),只 blit 面板+交汇带,**零内容重排**(内容已预渲染到 offscreen 或复用快照,与 §5.2 快照思想同源)。
|
||||
- **局部 dirty**:面板滑入滑出用 `meow_ui_flush_region` 刷边界带;内容行变化刷行块。
|
||||
|
||||
**复用组合**:B④ 顶栏=快捷设置(A① 控件组)+ 通知中心(A② 列表);底部面板=操作抽屉(`meow_btn` 组 / A② 动作行);侧边栏=A② + 导航。
|
||||
|
||||
**API 草案(「草案/待定案」,不实现;实现以 `meow_ui.h` 为准)**:
|
||||
```c
|
||||
typedef enum { MEOW_PANEL_TOP, MEOW_PANEL_BOTTOM, MEOW_PANEL_EDGE_R } meow_panel_edge;
|
||||
typedef struct meow_panel meow_panel;
|
||||
meow_panel *meow_ui_panel_create(meow_panel_edge e, int x, int y, int w, int h);
|
||||
void meow_ui_panel_set_content(meow_panel *p, meow_widget *content); /* 懒载:首展创建 */
|
||||
int meow_ui_panel_expand(meow_panel *p); /* 1=展开(短插值动画) 0=收合;返回位移 */
|
||||
int meow_ui_panel_is_open(const meow_panel *p);
|
||||
void meow_ui_panel_set_collapsed(meow_panel *p, int collapsed);
|
||||
```
|
||||
> 说明:顶部面板**默认不占用「顶部下滑=通知中心」**(§5.1)——顶部热区归属通知中心;快捷设置在通知中心内二段展开为**待定案**(见关键交互),实现前须列出可与左缘返回/通知中心分流的具体触达途径,勿凭空抢占。
|
||||
|
||||
---
|
||||
|
||||
## 6. 输入层 / 生命周期(B1 部分 + B2 衔接)
|
||||
|
||||
**B1(本阶段)**:应用不再自读 `/dev/input/event*`,meow_ui 建立输入线程,把按键/触摸翻译成语义事件回调:
|
||||
@@ -233,6 +497,54 @@ void meow_ui_swipe_hint(int x);
|
||||
- `meow_ui_run` 改为从 IPC 收启动链路(`MEOW_CHAIN`/`MEOW_ACTIVITY` 环境变量)初始化导航栈;
|
||||
- 返回 = 栈回退,到根才 `meow_ui_request_exit()`。**本文档 §5 的控件与 §3/§4 绘制在 B2 不变**,只换输入/导航后端。
|
||||
|
||||
### 6.1 控件生命周期与归属(Activity 栈 + 三层控件模型)[源:2026-08-30]
|
||||
|
||||
> **性质**:SDK 控件生命周期的权威约定(B1/B2 均遵守)。根治「跨页面控件残留」——控件命中/绘制必须严格绑定其所属页面,否则会出现"按钮已不可见但仍被触摸命中"(如全屏页触摸到主页按钮位置闪现)。
|
||||
|
||||
**核心:控件严格归属创建它的 Activity,不跨页面共享。**
|
||||
|
||||
#### 三层职责(从 App 到系统,风险从低到高)
|
||||
|
||||
| 层 | 谁负责 | 谁能用 | 生命周期 |
|
||||
|---|---|---|---|
|
||||
| **① 页面控件** | 归属唯一 owner Activity | App | 随 Activity 栈;owner 在栈顶(active)才绘制+响应触摸 |
|
||||
| **② App 跨 Activity 控件** | **SDK 托管**(逻辑+渲染,框架职责) | App 可声明使用 | 钉在 App 的 Activity 栈**之上**,跨 Activity 常驻 |
|
||||
| **③ 系统级控件** | MeowOS/SDK 框架内部 | **仅系统组件,用户 App 禁调用** | 随系统,不开放 |
|
||||
|
||||
- **① 页面控件**:`meow_btn_create` 等创建时绑定当前 Activity;命中(`live_btn_hit`)只在**当前 active Activity 的控件集**里找;对象**不销毁**(Activity 内对象池复用),弹栈回来自动恢复 → **回页面零重建**。
|
||||
- **② App 跨 Activity 控件**:因为 App 页面本身依赖 SDK,跨 Activity UI 也由 **SDK 负责逻辑与渲染**。App 用 `meow_ui_global_*`(如下)声明,SDK 托管(钉在 App 栈之上、切 Activity 仍存在、逻辑/命中统一调度)。例:App 内部底部播放栏(多 Activity 共享)。
|
||||
- **③ 系统级控件**:状态栏、通知中心入口、左缘返回/全屏滑条、电源菜单、全局返回手势指示等**全局叠加层**——**只留 SDK 内部接口位,用户侧 App 一律不可调用**(开放成「悬浮窗/全局叠加层」会引入遮挡、冲突、性能与安全风险)。App 这类需求只能走 SDK 标准能力,不得自行叠加全局层。
|
||||
|
||||
#### 交互分层(命中分流)
|
||||
触摸命中顺序:**③ 系统全局 → ② App 全局 → ① 当前 Activity 页面控件**;某层命中即消费,否则落到下一层。
|
||||
|
||||
#### 与 agent-119「即时重绘注册表」的关系
|
||||
`g_live_btns[]` 从进程级全局,改为**按 Activity 分区**的控件注册集;非 active Activity 的控件不参与命中。这直接根治 agent-119 遗留的"全屏页触摸到主界面按钮位置 → 短暂闪现 accent 底"(页面控件残留,跨页不复用)。
|
||||
|
||||
#### API 定案(本轮已在 B1 实现)
|
||||
```c
|
||||
/* ① Activity 栈 */
|
||||
void meow_ui_activity_push(int id);
|
||||
void meow_ui_activity_pop(void);
|
||||
int meow_ui_activity_active(void); /* 当前 active activity id */
|
||||
|
||||
/* ② App 跨 Activity 控件(SDK 托管) */
|
||||
typedef void (*meow_global_render_fn)(void *ctx); /* 每次渲染帧回调(SDK 调用) */
|
||||
typedef int (*meow_global_hit_fn)(void *ctx, int x, int y); /* 命中返回1=消费 */
|
||||
void meow_ui_global_add(int id, meow_global_render_fn r, meow_global_hit_fn h, void *ctx);
|
||||
void meow_ui_global_remove(int id);
|
||||
|
||||
/* ③ 系统级控件:仅框架内部,无公共 API(不开放) */
|
||||
```
|
||||
|
||||
#### 实现期定案 / 与上文的偏差(2026-08-30 落地,保持文档实时一致)
|
||||
- **控件绑定 owner**:`meow_btn_create` 等所有控件(btn/slider/switch/list)创建时即取 `meow_ui_activity_active()` 作为唯一 `owner`(`meow_widget` 新增 `int owner` 字段)。栈空时 `active()` 返回 **0(根/default Activity)**——未显式管理栈的 App 所有控件默认归属根 0。
|
||||
- **命中双闸门**:除 `live_btn_hit`(实时按压重绘)外,**公共 `meow_widget_hit` 同样仅限 `owner==active`** 才返回命中(页面控件只对自身 Activity 负责,不跨页复用)。SDK 侧 `meow_widget_touch_refresh` 另加 stale 保护:按压期间若发生 Activity 切换(如点 FULLSCREEN 进全屏),静默清除其按住引用、不绘制,杜绝在新页底上画出旧按钮 accent 残留。
|
||||
- **对象复用(非销毁)**:§6.1 的「Activity 内对象池复用」本轮**从简落地**——控件对象不随 pop 销毁,SDK 不维护独立对象池;App 自行持有控件指针(hello 用静态全局),弹栈回来自动恢复命中(零重建)。注册表按**指针去重**(`live_btn_register` 查重),故反复 push/pop 不重复注册、不泄漏。
|
||||
- **② 为可用骨架**:SDK 维护全局控件列表(`meow_ui_global.c`),渲染帧 `meow_ui_global_render()` 在 active activity 内容之上、全局状态栏之下调用 render_cb;触摸 TAP 先 `meow_ui_global_hit()`(返回 1=消费),否则落 `on_tap`。无 z 序细分/无按压态管理/无命中区排布(待 B2 细化);同 id `global_add` 幂等。
|
||||
- **③ 系统级(状态栏/通知中心/返回滑条/电源菜单)**:未开放任何公共悬浮/叠加层 API,既有状态栏/返回滑条逻辑原样保留。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 动画/时间(B1 最小可用)
|
||||
@@ -299,6 +611,8 @@ patch_v2/sdk/ # SDK 源码
|
||||
├── meow_ui.h # 对外 API(本文档 §3-§8)
|
||||
├── meow_ui_gfx.c # 渲染后端(back_buf+present+font)
|
||||
├── meow_ui_widget.c # 控件
|
||||
├── meow_ui_activity.c # §6.1 ① Activity 栈(控件归属)
|
||||
├── meow_ui_global.c # §6.1 ② App 跨 Activity 控件(SDK 托管骨架)
|
||||
├── meow_ui_img.c # stb_image 解码
|
||||
├── meow_ui_input.c # 输入线程+语义事件
|
||||
├── meow_ui_theme.c
|
||||
|
||||
Reference in new issue
Block a user