- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
158 lines
6.5 KiB
C
158 lines
6.5 KiB
C
/*
|
||
* meow_select.c — §5.8.6 枚举/预设选择器(M7.2 设置页缺口 #4)。
|
||
*
|
||
* 封装 = BottomSheet(标题 + 选项列表)+ meow_listview(SINGLE) 单选列表。选项用 meow_listview
|
||
* 渲染(单选高亮 primaryContainer、可滚动 meow_scroll 惯性);外层模态复用 meow_ui_modal_*
|
||
* + meow_ui_modal_capture/restore(与 meow_dialog 同源:scrim 只叠一层/关闭无残影)。
|
||
* 阻塞式(meow_input_pop 轮询);打开前排空残留触摸;点面板外/左缘返回 = 取消;点选项 = 选中 +
|
||
* 关闭 + on_change 回调。选项数组定长(≤MEOW_SELECT_MAX_ITEMS)。
|
||
*/
|
||
#include "meow_ui.h"
|
||
#include "include/meow_select.h"
|
||
#include "meow_ui_internal.h" /* meow_input_pop/drain + meow_ui_modal_capture/restore */
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
|
||
#define MEOW_SELECT_ROW 48 /* 选项行高(px) */
|
||
|
||
struct meow_select {
|
||
char title[96];
|
||
char items[MEOW_SELECT_MAX_ITEMS][64];
|
||
int nitems;
|
||
int cur; /* 初始/当前选中项 */
|
||
int result; /* 选中下标 / -1=取消 */
|
||
int done;
|
||
int h; /* 面板高度(0=自动) */
|
||
meow_select_fn cb;
|
||
void *ctx;
|
||
};
|
||
|
||
/* meow_listview src2 数据源:填 title=options[idx](右尾件无;enabled=1)。 */
|
||
static int select_src2(int idx, meow_list_item *out, void *ctx)
|
||
{
|
||
meow_select *s = (meow_select *)ctx;
|
||
if (idx < 0 || idx >= s->nitems) return 0;
|
||
memset(out, 0, sizeof *out);
|
||
out->title = s->items[idx];
|
||
out->right = MEOW_LIST_RIGHT_NONE;
|
||
out->enabled = 1;
|
||
return 1;
|
||
}
|
||
|
||
meow_select *meow_select_create(const char *title, int cur)
|
||
{
|
||
meow_select *s = (meow_select *)calloc(1, sizeof *s);
|
||
if (!s) return NULL;
|
||
if (title) { strncpy(s->title, title, sizeof s->title - 1); s->title[sizeof s->title - 1] = '\0'; }
|
||
s->cur = cur; s->result = -1; s->done = 0;
|
||
return s;
|
||
}
|
||
int meow_select_add_item(meow_select *s, const char *label)
|
||
{
|
||
if (!s || s->nitems >= MEOW_SELECT_MAX_ITEMS) return -1;
|
||
if (label) { strncpy(s->items[s->nitems], label, 63); s->items[s->nitems][63] = '\0'; }
|
||
int idx = s->nitems;
|
||
s->nitems++;
|
||
return idx;
|
||
}
|
||
void meow_select_set_on_change(meow_select *s, meow_select_fn cb, void *ctx)
|
||
{ if (s) { s->cb = cb; s->ctx = ctx; } }
|
||
|
||
int meow_select_open(meow_select *s)
|
||
{
|
||
if (!s || s->nitems <= 0) return -1;
|
||
const meow_theme *th = meow_theme_get();
|
||
meow_input_start();
|
||
meow_input_drain(); /* 排空残留触摸(goodix 长尾) */
|
||
|
||
s->done = 0; s->result = -1;
|
||
int W = meow_ui_width(), H = meow_ui_height();
|
||
int sb = meow_ui_statusbar_height(); if (sb < 0) sb = 0;
|
||
int pad = 24;
|
||
int title_h = meow_ui_text_height(th->font_title);
|
||
int rowh = MEOW_SELECT_ROW;
|
||
int avail = H - sb - 20;
|
||
int min_h = pad + title_h + 12 + rowh + 20;
|
||
int want = (s->h > 0) ? s->h : min_h;
|
||
int est = pad + title_h + 12 + s->nitems * rowh + 20;
|
||
if (est > want) want = est;
|
||
if (want > avail) want = avail;
|
||
if (want < min_h) want = (min_h < avail) ? min_h : avail;
|
||
int ph = want, py = H - ph; /* 底部面板(顶部圆角) */
|
||
int list_y = py + pad + title_h + 12;
|
||
int list_h = ph - (list_y - py) - pad; /* 底部余量 */
|
||
if (list_h < rowh) list_h = rowh;
|
||
|
||
/* 选项列表(meow_listview[SINGLE]:单选高亮 + 可滚动)。open 时创建,close 释放(冷路径)。 */
|
||
meow_widget *lv = meow_listview_create(0, list_y, W, list_h, s->nitems,
|
||
select_src2, s, MEOW_LIST_SEL_SINGLE);
|
||
if (!lv) return -1;
|
||
meow_listview_set_item_h(lv, rowh);
|
||
/* 定位初始选中项在视口内。 */
|
||
int target = s->cur * rowh - (list_h - rowh) / 2;
|
||
int maxs = meow_listview_max_scroll(lv);
|
||
if (target < 0) target = 0;
|
||
if (target > maxs) target = maxs;
|
||
meow_listview_set_scroll(lv, target);
|
||
meow_listview_set_sel(lv, s->cur);
|
||
meow_scroll *sc = meow_scroll_wrap(lv, 1); /* 惯性滚动(fling/snap) */
|
||
|
||
/* §6.4 模态作用域 + 背景快照(关闭即还原,无残影/不叠黑)。 */
|
||
meow_ui_modal *m = meow_ui_modal_begin();
|
||
meow_ui_modal_capture();
|
||
/* 首次绘制:遮罩 + 底部面板(顶部圆角)+ 标题 + 选项列表。 */
|
||
meow_ui_fill_rect_alpha(0, 0, W, H, 0x000000, 150);
|
||
meow_gfx_fill_round(0, py, W, ph, th->radius_card, th->surfaceContainerHighest);
|
||
meow_ui_text(pad, py + pad, s->title, th->font_title, th->onSurface);
|
||
meow_widget_draw(lv);
|
||
meow_ui_flush();
|
||
|
||
int dy_start = 0, down = 0;
|
||
while (!s->done) {
|
||
meow_input_ev e;
|
||
while (meow_input_pop(&e)) {
|
||
meow_ui_activity_ping(); /* 模态期间交互也重置息屏计时 */
|
||
if (e.type == MEOW_EV_TOUCH_DOWN) { down = 1; dy_start = e.b; }
|
||
else if (e.type == MEOW_EV_TOUCH_MOVE) {
|
||
if (down && sc) {
|
||
meow_scroll_track(sc, e.b - dy_start, meow_ui_time_ms());
|
||
dy_start = e.b;
|
||
}
|
||
} else if (e.type == MEOW_EV_TAP) {
|
||
int x = e.a, y = e.b;
|
||
if (y < py) { s->done = 1; s->result = -1; break; } /* 点面板外 = 取消 */
|
||
int idx = meow_listview_tap_at(lv, x, y); /* 单选高亮 = 选中 */
|
||
if (idx >= 0) {
|
||
s->result = idx; s->cur = idx;
|
||
if (s->cb) s->cb(idx, s->ctx); /* 关闭即回调 */
|
||
s->done = 1;
|
||
}
|
||
/* 面板内但未命中项:保持打开(等下一次点击)。 */
|
||
} else if (e.type == MEOW_EV_SWIPE) {
|
||
if (e.a == MEOW_SWIPE_LEFT) { s->done = 1; s->result = -1; } /* 返回 = 取消 */
|
||
else if (sc) meow_scroll_fling(sc);
|
||
}
|
||
}
|
||
meow_anim_tick(); /* 推进 fling */
|
||
if (!s->done) usleep(16000);
|
||
}
|
||
meow_ui_modal_end(m);
|
||
meow_ui_modal_restore();
|
||
if (sc) meow_scroll_free(sc);
|
||
meow_widget_free(lv);
|
||
return s->result;
|
||
}
|
||
void meow_select_free(meow_select *s) { if (s) free(s); }
|
||
|
||
int meow_select_show(const char *title, const char *const *opts, int n, int cur)
|
||
{
|
||
if (!opts || n <= 0) return -1;
|
||
meow_select *s = meow_select_create(title, cur);
|
||
if (!s) return -1;
|
||
for (int i = 0; i < n && i < MEOW_SELECT_MAX_ITEMS; i++) meow_select_add_item(s, opts[i]);
|
||
int r = meow_select_open(s);
|
||
meow_select_free(s);
|
||
return r;
|
||
}
|