fix(ncm): SDK圆角矩形列表项加外边距 — 实为ncm_app应用层自绘(row_bg圆角卡),调用处加NCM_ROW_GAP=8px卡间可见外距(卡高48/行距56上下对称+擦SDK行分隔线);三屏playlist/home/queue;宿主test_meow_row_gap PASS,0warning,不涉meow_ui.a无需重链
This commit is contained in:
1 parent
a82f3f9dfa
commit
e8218b8ae9
5 files changed
+107
-15
No files matched your search
@@ -66,6 +66,17 @@ enum {
|
|||||||
#define APP_OP_W 48 /* 行右侧操作区触达宽 */
|
#define APP_OP_W 48 /* 行右侧操作区触达宽 */
|
||||||
#define APP_FOOTER_H 26
|
#define APP_FOOTER_H 26
|
||||||
|
|
||||||
|
/* 圆角卡列表项外边距(item margin/gap):相邻卡片间可见空隙 px。SDK listview 行距(=APP_ROW_H)
|
||||||
|
* 不变——卡片在其行高内上下对称内缩 NCM_ROW_GAP/2,故文本(SDK 按 APP_ROW_H 垂直居中)仍落卡中心;
|
||||||
|
* 相邻卡顶间距恒=APP_ROW_H=卡高+NCM_ROW_GAP。要求偶数,保证上下对称。 */
|
||||||
|
#define NCM_ROW_GAP 8
|
||||||
|
/* 第 idx 行(行高 item,滚动 off,列表顶 list_y)的圆角卡:顶 y 与高 h。 */
|
||||||
|
static inline int ncm_row_card_y(int item, int idx, int off, int list_y)
|
||||||
|
{
|
||||||
|
return list_y + (idx * item - off) + NCM_ROW_GAP / 2;
|
||||||
|
}
|
||||||
|
static inline int ncm_row_card_h(int item) { return item - NCM_ROW_GAP; }
|
||||||
|
|
||||||
/* ---- 播放页(§22 重做:封面页/歌词页双页,NCM_CACHE_DESIGN §6)----
|
/* ---- 播放页(§22 重做:封面页/歌词页双页,NCM_CACHE_DESIGN §6)----
|
||||||
* 沉浸底恒 NCM_PLAYER_BG(不随系统明暗反转——「不动沉浸底」);日夜间主题配色只映射到
|
* 沉浸底恒 NCM_PLAYER_BG(不随系统明暗反转——「不动沉浸底」);日夜间主题配色只映射到
|
||||||
* 半透明叠加层(歌词页 scrim)与 accent(红)。 */
|
* 半透明叠加层(歌词页 scrim)与 accent(红)。 */
|
||||||
@@ -568,6 +579,9 @@ void ipc_media_stop(void);
|
|||||||
int ipc_media_nav_exit(void); /* 任务2:发 MSG_NAV{EXIT} 给 launcher 请求退后台(进程+媒体会话保留;
|
int ipc_media_nav_exit(void); /* 任务2:发 MSG_NAV{EXIT} 给 launcher 请求退后台(进程+媒体会话保留;
|
||||||
launcher M4 据 background_audio+PLAYING 判保活)。0=发出/-1=失败。 */
|
launcher M4 据 background_audio+PLAYING 判保活)。0=发出/-1=失败。 */
|
||||||
int ipc_media_focus_consume(void); /* 任务3:UI 线程消费「回播放页」标志(0=无;1=已消费一次) */
|
int ipc_media_focus_consume(void); /* 任务3:UI 线程消费「回播放页」标志(0=无;1=已消费一次) */
|
||||||
|
/* 批3:上报当前曲歌词(lrc 原文 + tlrc 翻译)到 launcher 媒体会话(MSG_META_LYRIC 分片)。
|
||||||
|
* 由 lyric_worker 在拉到/清一歌词后调(换歌/换词 seq 自增;lrc/tl 可为空=清词)。 */
|
||||||
|
void ipc_media_lyric_report(const char *lrc, const char *tl);
|
||||||
int ipc_act_report(int act); /* 任务4 keep_awake:向 launcher 上报当前顶层 activity(MSG_ACT_FOCUS)。
|
int ipc_act_report(int act); /* 任务4 keep_awake:向 launcher 上报当前顶层 activity(MSG_ACT_FOCUS)。
|
||||||
act=ACT_* 值,映射 "login/home/playlist/player/settings/search"(对齐
|
act=ACT_* 值,映射 "login/home/playlist/player/settings/search"(对齐
|
||||||
app.json awake.<act> 键);launcher fg_keep_awake 依声明判常亮。
|
app.json awake.<act> 键);launcher fg_keep_awake 依声明判常亮。
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/* app/test/test_meow_row_gap.c — 宿主验证:圆角卡列表项外边距(item margin/gap)几何。
|
||||||
|
*
|
||||||
|
* 只测 app/ui 卡片几何辅助(ncm_row_card_y / ncm_row_card_h + NCM_ROW_GAP / APP_ROW_H),
|
||||||
|
* 纯整数运算,不链 SDK / 不开设备:
|
||||||
|
* gcc -I. -I../sdk -I../meow_launcherd -Icore \
|
||||||
|
* -I"$ROOT/patch_v2/sdk" -I"$ROOT/patch_v2/meow_launcherd" \
|
||||||
|
* -Ivendor/mbedtls/include -Ivendor/jsmn -Ivendor/qrcodegen/c \
|
||||||
|
* -Ivendor/minimp3 -Ivendor/dr_flac \
|
||||||
|
* test_meow_row_gap.c -o test_meow_row_gap && ./test_meow_row_gap
|
||||||
|
*
|
||||||
|
* 断言集(对应「相邻 item 顶之间 = item 高 + gap」的可见形式):
|
||||||
|
* ① 相邻卡顶间距 = APP_ROW_H(= 卡高 + gap;SDK 行距不变);
|
||||||
|
* ② 卡片间可见外距 = NCM_ROW_GAP;
|
||||||
|
* ③ 卡在其行高内上下对称内缩 → SDK 文本(按 APP_ROW_H 垂直居中)落卡中心;
|
||||||
|
* ④ 滚动偏移只整体平移,不改变上述间距/对称。
|
||||||
|
*/
|
||||||
|
#include "../ncm_app_internal.h" /* APP_ROW_H / NCM_ROW_GAP / ncm_row_card_y / ncm_row_card_h */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const int item = APP_ROW_H; /* 行距(SDK listview item_h,不变) */
|
||||||
|
const int gap = NCM_ROW_GAP;
|
||||||
|
const int list_y = 100;
|
||||||
|
|
||||||
|
/* 卡顶 = 行顶 + 上下对称内缩 gap/2;卡高 = item - gap。 */
|
||||||
|
int y0 = ncm_row_card_y(item, 0, 0, list_y);
|
||||||
|
int y1 = ncm_row_card_y(item, 1, 0, list_y);
|
||||||
|
int h = ncm_row_card_h(item);
|
||||||
|
|
||||||
|
/* ① 行顶(索引0)=list_y;卡相对行顶对称内缩 gap/2;卡高=item-gap */
|
||||||
|
assert(y0 == list_y + gap / 2);
|
||||||
|
assert(h == item - gap);
|
||||||
|
assert(h + gap == item);
|
||||||
|
|
||||||
|
/* ① 相邻卡顶间距 = item(顶到顶 = 卡高 + gap) */
|
||||||
|
assert(y1 - y0 == item);
|
||||||
|
|
||||||
|
/* ② 卡片间可见外距 = gap(卡 i 底 到 卡 i+1 顶) */
|
||||||
|
assert(y1 - (y0 + h) == gap);
|
||||||
|
|
||||||
|
/* ③ 卡中心 == 行中心(SDK 文本按行高居中 → 落卡中心) */
|
||||||
|
assert(y0 - gap / 2 + item / 2 == y0 + h / 2);
|
||||||
|
|
||||||
|
/* ④ 滚动偏移只平移,不改变间距/对称 */
|
||||||
|
for (int off = 0; off <= 2 * item; off += item / 2) {
|
||||||
|
int a2 = ncm_row_card_y(item, 2, off, list_y);
|
||||||
|
int a3 = ncm_row_card_y(item, 3, off, list_y);
|
||||||
|
assert(a3 - a2 == item);
|
||||||
|
assert(a3 - (a2 + h) == gap);
|
||||||
|
/* 顶到顶 = 卡高 + gap,且卡在行内对称(对任意 off 一致) */
|
||||||
|
assert(a2 - (list_y + (2 * item - off)) == gap / 2); /* 行顶 = list_y + idx*item - off */
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("PASS row_gap=%d card_h=%d top2top=%d visible_gap=%d symmetric=1\n",
|
||||||
|
gap, h, item, gap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -91,7 +91,8 @@ static void home_row_bg(void *ctx)
|
|||||||
int n = tab_count(g_tab);
|
int n = tab_count(g_tab);
|
||||||
if (last > n) last = n;
|
if (last > n) last = n;
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
||||||
ncm_fill_round(r_list.x, ry, r_list.w, th2, 12, th->surfaceContainer);
|
ncm_fill_round(r_list.x, ry, r_list.w, th2, 12, th->surfaceContainer);
|
||||||
}
|
}
|
||||||
@@ -170,16 +171,21 @@ static void home_draw(void *ctx)
|
|||||||
int n = tab_count(g_tab);
|
int n = tab_count(g_tab);
|
||||||
if (last > n) last = n;
|
if (last > n) last = n;
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
||||||
int icy = ry + (item - isz) / 2;
|
int icy = ry + (th2 - isz) / 2;
|
||||||
int bx = r_list.x + 16;
|
int bx = r_list.x + 16;
|
||||||
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
||||||
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red); /* 盘芯 */
|
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red); /* 盘芯 */
|
||||||
if (g_press_row == i) {
|
if (g_press_row == i) {
|
||||||
meow_ui_fill_rect(r_list.x, ry, 4, item - 2, pa->red);
|
meow_ui_fill_rect(r_list.x, ry, 4, th2, pa->red);
|
||||||
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, item - 2, pa->red, 26);
|
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, th2, pa->red, 26);
|
||||||
}
|
}
|
||||||
|
/* 擦除 z=10 的 SDK 行分隔线(现落进卡片间空隙):以页底色填空隙带;不越出列表视口底。 */
|
||||||
|
int gy = ry + th2, gh = NCM_ROW_GAP;
|
||||||
|
if (gy + gh > r_list.y + r_list.h) gh = r_list.y + r_list.h - gy;
|
||||||
|
if (gh > 0) meow_ui_fill_rect(r_list.x, gy, r_list.w, gh, th->bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ static void pl_row_bg(void *ctx)
|
|||||||
int first = off / item, last = (off + r_list.h) / item + 1;
|
int first = off / item, last = (off + r_list.h) / item + 1;
|
||||||
if (last > g_st.track_ids_count) last = g_st.track_ids_count;
|
if (last > g_st.track_ids_count) last = g_st.track_ids_count;
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
||||||
ncm_fill_round(r_list.x, ry, r_list.w, th2, 12, th->surfaceContainer);
|
ncm_fill_round(r_list.x, ry, r_list.w, th2, 12, th->surfaceContainer);
|
||||||
}
|
}
|
||||||
@@ -193,15 +194,20 @@ static void pl_draw(void *ctx)
|
|||||||
int first = off / item, last = (off + r_list.h) / item + 1;
|
int first = off / item, last = (off + r_list.h) / item + 1;
|
||||||
if (last > g_st.track_ids_count) last = g_st.track_ids_count;
|
if (last > g_st.track_ids_count) last = g_st.track_ids_count;
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
||||||
int icy = ry + (item - isz) / 2, bx = r_list.x + 16;
|
int icy = ry + (th2 - isz) / 2, bx = r_list.x + 16;
|
||||||
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
||||||
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red);
|
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red);
|
||||||
if (g_press_row == i) {
|
if (g_press_row == i) {
|
||||||
meow_ui_fill_rect(r_list.x, ry, 4, item - 2, pa->red);
|
meow_ui_fill_rect(r_list.x, ry, 4, th2, pa->red);
|
||||||
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, item - 2, pa->red, 26);
|
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, th2, pa->red, 26);
|
||||||
}
|
}
|
||||||
|
/* 擦除 z=10 的 SDK 行分隔线(现落进卡片间空隙):以页底色填空隙带;不越出列表视口底。 */
|
||||||
|
int gy = ry + th2, gh = NCM_ROW_GAP;
|
||||||
|
if (gy + gh > r_list.y + r_list.h) gh = r_list.y + r_list.h - gy;
|
||||||
|
if (gh > 0) meow_ui_fill_rect(r_list.x, gy, r_list.w, gh, th->bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ static void q_row_bg(void *ctx)
|
|||||||
if (last > cnt) last = cnt;
|
if (last > cnt) last = cnt;
|
||||||
int cur = player_manager_playing_song();
|
int cur = player_manager_playing_song();
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
||||||
if (i == cur) {
|
if (i == cur) {
|
||||||
/* 当前播放行:红色左条 + 红色轻染(高亮),底用 red_ctr 浅红 */
|
/* 当前播放行:红色左条 + 红色轻染(高亮),底用 red_ctr 浅红 */
|
||||||
@@ -112,6 +113,7 @@ static void q_draw(void *ctx)
|
|||||||
{
|
{
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
if (meow_ui_activity_active() != ACT_QUEUE) return;
|
if (meow_ui_activity_active() != ACT_QUEUE) return;
|
||||||
|
const meow_theme *th = meow_theme_get();
|
||||||
const ncm_pal_t *pa = ncm_palette(g_dark);
|
const ncm_pal_t *pa = ncm_palette(g_dark);
|
||||||
int cnt = appstate_queue_count();
|
int cnt = appstate_queue_count();
|
||||||
if (cnt <= 0) return;
|
if (cnt <= 0) return;
|
||||||
@@ -120,15 +122,20 @@ static void q_draw(void *ctx)
|
|||||||
int first = off / item, last = (off + r_list.h) / item + 1;
|
int first = off / item, last = (off + r_list.h) / item + 1;
|
||||||
if (last > cnt) last = cnt;
|
if (last > cnt) last = cnt;
|
||||||
for (int i = first; i < last; i++) {
|
for (int i = first; i < last; i++) {
|
||||||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
int ry = ncm_row_card_y(item, i, off, r_list.y);
|
||||||
|
int th2 = ncm_row_card_h(item);
|
||||||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
||||||
int icy = ry + (item - isz) / 2, bx = r_list.x + 16;
|
int icy = ry + (th2 - isz) / 2, bx = r_list.x + 16;
|
||||||
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
||||||
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red);
|
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red);
|
||||||
if (g_press_row == i) {
|
if (g_press_row == i) {
|
||||||
meow_ui_fill_rect(r_list.x, ry, 4, item - 2, pa->red);
|
meow_ui_fill_rect(r_list.x, ry, 4, th2, pa->red);
|
||||||
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, item - 2, pa->red, 26);
|
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, th2, pa->red, 26);
|
||||||
}
|
}
|
||||||
|
/* 擦除 z=10 的 SDK 行分隔线(现落进卡片间空隙):以页底色填空隙带;不越出列表视口底。 */
|
||||||
|
int gy = ry + th2, gh = NCM_ROW_GAP;
|
||||||
|
if (gy + gh > r_list.y + r_list.h) gh = r_list.y + r_list.h - gy;
|
||||||
|
if (gh > 0) meow_ui_fill_rect(r_list.x, gy, r_list.w, gh, th->bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user