Files
2026-06-07 22:53:58 +08:00

820 lines
25 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---@class (exact) ShowcaseAction
---@field text string
---@field text_en? string
---@field handler string
---@class (exact) ShowcaseExample
---@field id string
---@field group string
---@field group_en? string
---@field category string
---@field category_en? string
---@field menu string
---@field menu_en? string
---@field title string
---@field title_en? string
---@field summary string
---@field summary_en? string
---@field code string
---@field params string
---@field params_en? string
---@field actions ShowcaseAction[]
---@class ShowcaseExamples
local examples = {}
---@type ShowcaseExample[]
examples.items = {
{
id = "nodes",
group = "基础功能",
group_en = "Basics",
category = "节点",
category_en = "Nodes",
menu = "基础节点",
menu_en = "Nodes",
title = "RuntimeNode 基础组件",
title_en = "RuntimeNode primitives",
summary = "基础节点、交互和属性更新。",
summary_en = "Primitive nodes, interaction and property updates.",
code = [[local runtime_ui = runtime.import("runtime_ui")
runtime_ui.circle("hero", {
x = 80,
y = 64,
size = 48,
color = "#ff22c55e",
interactive = true,
handler = "demo_anim"
})]],
params = [[参数说明type/circle/rect/line 定义节点类型;
x/y/width/height 定位尺寸;
w/h 是 width/height 的便利别名;
size 会同时设置 width 和 height
handler/onClick 是 onTap 的便利别名;
color/alpha/scale/rotation 控制表现;
interactive/onTap 打开点击事件。
填写样例:
runtime_ui.circle("hero", {
x = 80,
y = 64,
size = 48,
color = "#ff22c55e",
alpha = 0.9,
scale = 1.0,
interactive = true,
handler = "demo_anim"
})]],
params_en = [[Params: type/circle/rect/line choose node kind;
x/y/width/height place it;
color/alpha/scale/rotation style it;
interactive/onTap enable taps.]],
actions = {
{ text = "更新进度", text_en = "Progress", handler = "demo_progress" },
{ text = "显隐/透明", text_en = "Visibility", handler = "demo_visibility" }
}
},
{
id = "text_demo",
group = "基础功能",
group_en = "Basics",
category = "文本",
category_en = "Text",
menu = "文本",
menu_en = "Text",
title = "Text 文本组件",
title_en = "Text component",
summary = "当前支持纯文本、颜色和字号;暂不支持富文本。",
summary_en = "Plain text, color and font size; rich text is not supported yet.",
code = [[runtime_ui.text("label", "Hello Lua", 20, 40, 220, 28, {
color = "#ffe2e8f0",
fontSize = 18
})
-- 当前协议没有 richText/spans 字段]],
params = [[参数说明text 是纯文本;
color/fontSize/alpha 控制整体样式;
textAlign 可填 "left" / "center" / "right"
当前没有 richText/spans不能做局部文字样式。
填写样例:
runtime_ui.text("label", "Hello Lua", 20, 40, 220, 28, {
color = "#ffe2e8f0",
fontSize = 18,
textAlign = "left"
})]],
params_en = [[Params: text is plain copy;
color/fontSize/alpha style the whole node;
richText/spans are not supported yet.]],
actions = {
{ text = "改文案", text_en = "Change", handler = "demo_text_change" },
{ text = "样式切换", text_en = "Style", handler = "demo_text_style" }
}
},
{
id = "buttons",
group = "基础功能",
group_en = "Basics",
category = "按钮",
category_en = "Buttons",
menu = "按钮交互",
menu_en = "Buttons",
title = "基础按钮和点击事件",
title_en = "Buttons and tap events",
summary = "button 节点、onTap handler、状态更新和禁用态。",
summary_en = "Button nodes, onTap handlers, state updates and disabled style.",
code = [[runtime_ui.button("ok", {
text = "确认",
x = 20,
y = 40,
w = 120,
h = 34,
handler = "submit",
color = theme.primary,
radius = 10,
fontSize = 13,
asset = "button_normal",
pressedAsset = "button_pressed",
disabledAsset = "button_disabled"
})
-- asset/pressedAsset/disabledAsset 都是 manifest image 资源 key。
-- event.handler == "submit" 时返回 Diff/Command]],
params = [[参数说明button = 背景 + 文本 + onTap
w/h 是 width/height 的便利别名;
handler/onClick 是 onTap 的便利别名;
color/radius/fontSize 控制样式;
asset/pressedAsset/disabledAsset 可配置 normal/pressed/disabled 三态图片;
interactive=false 可禁用命中并使用 disabledAsset。
填写样例:
runtime_ui.button("ok", {
text = "确认",
x = 20,
y = 40,
w = 120,
h = 34,
handler = "submit",
color = theme.primary,
radius = 10,
fontSize = 13,
asset = "button_normal",
pressedAsset = "button_pressed",
disabledAsset = "button_disabled",
interactive = true
})]],
params_en = [[Params: button combines background, label and onTap;
color/radius/fontSize style it;
interactive=false disables hit testing.]],
actions = {
{ text = "点击按钮", text_en = "Tap", handler = "demo_button_primary" },
{ text = "切换状态", text_en = "Toggle", handler = "demo_button_toggle" }
}
},
{
id = "button_images",
group = "基础功能",
group_en = "Basics",
category = "按钮",
category_en = "Buttons",
menu = "按钮三态图",
menu_en = "Button skins",
title = "Button 三态图片",
title_en = "Button state images",
summary = "button 使用 normal / pressed / disabled 三态图片资源。",
summary_en = "Buttons can render normal, pressed and disabled image assets.",
code = [[runtime_ui.button("start", {
text = "开始",
x = 20,
y = 40,
w = 132,
h = 40,
handler = "start",
asset = "button_normal",
pressedAsset = "button_pressed",
disabledAsset = "button_disabled"
})
runtime_ui.button("locked", {
text = "禁用",
x = 170,
y = 40,
w = 132,
h = 40,
handler = "noop",
asset = "button_normal",
pressedAsset = "button_pressed",
disabledAsset = "button_disabled",
interactive = false
})]],
params = [[参数说明:
asset = normal 状态图片资源 key
pressedAsset = 按下状态图片资源 key
disabledAsset = 禁用状态图片资源 key
interactive=false 时 Runtime 自动选择 disabledAsset
按住按钮时 Runtime 自动切换 pressedAsset
未配置对应状态图片时回退到 asset再回退到 color/radius 背景。
manifest 示例:
"button_normal": { "type": "image", "path": "assets/button_normal.png" },
"button_pressed": { "type": "image", "path": "assets/button_pressed.png" },
"button_disabled": { "type": "image", "path": "assets/button_disabled.png" }]],
params_en = [[Params:
asset is the normal-state image resource key;
pressedAsset is used while the button is pressed;
disabledAsset is used when interactive=false;
missing state images fall back to asset, then to color/radius background.]],
actions = {
{ text = "点击图片按钮", text_en = "Tap", handler = "demo_button_image_tap" },
{ text = "切换禁用", text_en = "Toggle", handler = "demo_button_image_toggle" }
}
},
{
id = "sprites",
group = "基础功能",
group_en = "Basics",
category = "精灵",
category_en = "Sprites",
menu = "图片精灵",
menu_en = "Sprites",
title = "图片和 Sprite 节点",
title_en = "Image and sprite nodes",
summary = "image/sprite 使用 manifest 资源 key不暴露真实路径。",
summary_en = "Image/sprite nodes use manifest resource keys, not raw paths.",
code = [[runtime_ui.image("avatar", "sample_image", 24, 48, 56, 56)
runtime_ui.sprite("icon", "sample_image", 104, 48, 56, 56, {
layer = 20
})]],
params = [[参数说明asset 必须是 manifest 资源 key
image/sprite 不暴露真实路径;
layer 控制绘制顺序。
填写样例:
-- manifest.resources.sample_image.type = "image"
runtime_ui.image("avatar", "sample_image", 24, 48, 56, 56, {
layer = 20,
alpha = 1
})]],
params_en = [[Params: asset must be a manifest resource key;
image/sprite never expose raw paths;
layer controls draw order.]],
actions = {
{ text = "精灵动画", text_en = "Animate", handler = "demo_sprite_anim" },
{ text = "切换样式", text_en = "Style", handler = "demo_sprite_style" }
}
},
{
id = "radio_group",
group = "基础功能",
group_en = "Basics",
category = "选择",
category_en = "Selection",
menu = "RadioGroup",
menu_en = "Radio",
title = "RadioGroup 组合模式",
title_en = "RadioGroup composition",
summary = "Lua 用 circle/text/button 组合单选项。",
summary_en = "Lua composes radio options from circle/text/button nodes.",
code = [[-- RadioGroup 不是 Dart 原生控件
-- Lua 输出普通 RuntimeNodecircle + text + button
runtime_ui.circle("radio_dot", 24, 52, 14, { color = theme.primary })
runtime_ui.text("radio_label", "Audio", 46, 49, 120, 20)]],
params = [[参数说明RadioGroup 是 Lua 组合,不是原生控件;
用 circle/text/button 组合,并由 Lua state 保存选中值。
填写样例:
local option = { key = "audio", label = "Audio", y = 72 }
runtime_ui.circle("radio_" .. option.key .. "_dot", 18, option.y, 14, {
color = selected and theme.primary or "#ff475569"
})
runtime_ui.button("radio_" .. option.key .. "_hit", "", 8, option.y - 4, 180, 24, "demo_radio_audio", {
color = "#00000000",
interactive = true
})]],
params_en = [[Params: RadioGroup is Lua composition, not a native control;
compose circle/text/button and keep selection in Lua state.]],
actions = {
{ text = "选 Audio", text_en = "Audio", handler = "demo_radio_audio" },
{ text = "选 Spine", text_en = "Spine", handler = "demo_radio_spine" },
{ text = "选 Lua", text_en = "Lua", handler = "demo_radio_lua" }
}
},
{
id = "list_view",
group = "基础功能",
group_en = "Basics",
category = "列表",
category_en = "List",
menu = "ListView",
menu_en = "List",
title = "原生 ListView 容器",
title_en = "Native ListView container",
summary = "双轴滚动、惯性、回调、滚动条样式和虚拟化。",
summary_en = "Two-axis scroll, inertia, callbacks, styled scrollbar and culling.",
code = [[runtime_ui.list_view("list", 16, 42, 260, 72, {
contentWidth = 420,
contentHeight = 150,
scrollX = state.list_scroll_x,
scrollY = state.list_scroll_y,
virtualized = true,
cacheExtent = 24,
inertia = true,
onScroll = "demo_list_scrolled"
})
runtime_ui.button("row_1", "Lua", 8, 8, 220, 24, "select", {
parent = "list"
})]],
params = [[参数说明scrollX/scrollY 是双轴偏移;
contentWidth/contentHeight 是内容尺寸;
virtualized/cacheExtent 控制直接子节点裁剪;
inertia 开启拖动惯性;
onScroll 接收滚动回调;
scrollbarVisible=false 可隐藏滚动条;
scrollbarThumbColor/scrollbarTrackColor/scrollbarThickness 控制样式。
填写样例:
local opts = {
contentWidth = 420,
contentHeight = 150,
scrollX = 0,
scrollY = 0,
virtualized = true,
cacheExtent = 24,
inertia = true,
onScroll = "demo_list_scrolled",
scrollbarVisible = false
}
runtime_ui.list_view("list", 16, 42, 260, 72, opts)
-- 子节点必须把 parent 指向 listView
runtime_ui.button("row_1", "Lua", 8, 8, 220, 24, "select", {
parent = "list"
})]],
params_en = [[Params: scrollX/scrollY are two-axis offsets;
contentWidth/contentHeight define content size;
virtualized/cacheExtent cull children;
inertia enables momentum;
onScroll emits callbacks;
scrollbar* styles bars.]],
actions = {
{ text = "横/竖排列", text_en = "Axis", handler = "demo_list_horizontal" },
{ text = "下一项", text_en = "Next", handler = "demo_list_next" },
{ text = "重置滚动", text_en = "Reset", handler = "demo_list_reset" }
}
},
{
id = "particles",
group = "基础功能",
group_en = "Basics",
category = "特效",
category_en = "Effects",
menu = "粒子特效",
menu_en = "Particles",
title = "Particle 粒子特效",
title_en = "Particle effects",
summary = "Lua 描述粒子参数Dart Runtime 创建 Flame 粒子组件。",
summary_en = "Lua describes particle params; Dart Runtime creates Flame particles.",
code = [[runtime_ui.particle("hit_fx", 220, 140, 160, 160, {
preset = "burst",
count = 40,
duration = 0.6,
color = "#ffffcc33",
colorTo = "#00ffcc33",
radius = 2.4,
radiusTo = 0,
speedMin = 60,
speedMax = 180,
gravityY = 120,
spread = 360,
autoRemove = true,
fadeOut = true,
layer = 80
})]],
params = [[参数说明particle 是 Runtime 原生节点Lua 不持有 Flame 粒子对象;
preset 可填 "burst" / "trail" / "snow" / "confetti"
count 是粒子数量;
duration 是生命周期秒数;
color/colorTo 控制颜色渐变;
radius/radiusTo 控制尺寸变化;
speedMin/speedMax 控制初速度范围;
gravityX/gravityY 控制加速度;
spread 控制发散角度;
autoRemove=true 表示生命周期结束后自动移除;
fadeOut=true 表示随进度淡出。
填写样例:
local opts = {
preset = "confetti",
count = 72,
duration = 1.2,
color = "#ffff4d6d",
colorTo = "#fffacc15",
radius = 2.6,
radiusTo = 0,
speedMin = 120,
speedMax = 260,
gravityY = 240,
spread = 90,
autoRemove = true,
fadeOut = true
}
runtime_ui.particle("win_fx", 280, 72, 220, 160, opts)]],
params_en = [[Params: particle is a native Runtime node; Lua never owns Flame particle objects;
preset: burst/trail/snow/confetti;
count controls particle amount;
duration is lifetime in seconds;
color/colorTo define gradient;
radius/radiusTo define size change;
speedMin/speedMax define initial speed;
gravityX/gravityY define acceleration;
spread defines emission angle;
autoRemove removes after lifetime;
fadeOut fades by progress.]],
actions = {
{ text = "爆发", text_en = "Burst", handler = "demo_particle_burst" },
{ text = "彩纸", text_en = "Confetti", handler = "demo_particle_confetti" },
{ text = "雪花", text_en = "Snow", handler = "demo_particle_snow" }
}
},
{
id = "layout_demo",
group = "基础功能",
group_en = "Basics",
category = "布局",
category_en = "Layout",
menu = "布局 Helper",
menu_en = "Layout",
title = "Lua layout helper",
title_en = "Lua layout helper",
summary = "layout.row/column/box 消费临时 margin不污染协议。",
summary_en = "layout.row/column/box consume temporary margin without polluting protocol tables.",
code = [[local layout = runtime.import("layout")
layout.box("panel", {
runtime_ui.rect("a", 0, 0, 42, 28),
runtime_ui.rect("b", 0, 0, 42, 28),
runtime_ui.rect("c", 0, 0, 42, 28),
runtime_ui.rect("d", 0, 0, 42, 28)
}, {
x = 16,
y = 48,
rows = 2,
columns = 2,
cellWidth = 58,
cellHeight = 34,
gapX = 8,
gapY = 8,
align = "center",
valign = "center"
})]],
params = [[参数说明layout.item 的 margin 只用于 Lua 布局计算,不会进入 RuntimeNode props
row/column 处理单轴排列;
box 按 rows/columns 把节点排成几排几列;
cellWidth/cellHeight 是单元格尺寸;
gapX/gapY 是列间距和行间距;
align/valign 控制节点在单元格内的水平/垂直对齐。
填写样例:
layout.box("panel", {
layout.item(runtime_ui.rect("a", 0, 0, 42, 28), { marginRight = 4 }),
runtime_ui.rect("b", 0, 0, 42, 28),
runtime_ui.rect("c", 0, 0, 42, 28),
runtime_ui.rect("d", 0, 0, 42, 28)
}, {
x = 16,
y = 48,
rows = 2,
columns = 2,
cellWidth = 58,
cellHeight = 34,
gapX = 8,
gapY = 8,
align = "center",
valign = "center"
})]],
params_en = [[Params: layout.item margins are Lua-only layout metadata and never enter RuntimeNode props;
box uses rows/columns to place nodes in a grid;
cellWidth/cellHeight define cells;
gapX/gapY define column and row gaps;
align/valign align each node inside its cell.]],
actions = {
{ text = "横向布局", text_en = "Row", handler = "demo_layout_row" },
{ text = "纵向布局", text_en = "Column", handler = "demo_layout_column" },
{ text = "Box 网格", text_en = "Box", handler = "demo_layout_box" }
}
},
{
id = "diff",
group = "运行协议",
group_en = "Runtime Protocol",
category = "Diff",
category_en = "Diff",
menu = "Diff 更新",
menu_en = "Diff",
title = "GameDiff 创建、更新、移除",
title_en = "GameDiff create/update/remove",
summary = "Diff 创建、更新、移除节点。",
summary_en = "Create, update and remove nodes with GameDiff.",
code = [[return {
render = {
creates = { node },
updates = { { id = "node", props = { x = 120 } } },
removes = { { id = "node" } }
}
}]],
params = [[参数说明creates 创建节点;
updates 只更新 props
removes 只需要 id。
Runtime 会白名单校验未知字段。
填写样例:
return {
ui = {
creates = {
runtime_ui.text("tip", "Hello", 20, 20, 160, 24, { textAlign = "left" })
},
updates = {
{ id = "tip", props = { text = "Updated", color = "#ffffa000" } }
},
removes = {
{ id = "tip" }
}
}
}]],
params_en = [[Params: creates add nodes;
updates patch props;
removes only need ids.
Runtime rejects unknown fields by whitelist.]],
actions = {
{ text = "创建/删除", text_en = "Create/remove", handler = "demo_temp" },
{ text = "Toast", text_en = "Toast", handler = "demo_toast" }
}
},
{
id = "commands",
group = "运行协议",
group_en = "Runtime Protocol",
category = "命令",
category_en = "Commands",
menu = "命令动画",
menu_en = "Commands",
title = "RuntimeCommand 动作和组合",
title_en = "RuntimeCommand actions",
summary = "动作、组合、取消和完成回调。",
summary_en = "Actions, composition, cancellation and callbacks.",
code = [[commands.sequence({
commands.move_to("actor", 220, 104, { duration = 0.55 }),
commands.parallel({
commands.scale_to("actor", 1.45, { duration = 0.35 }),
commands.fade_to("actor", 0.45, { duration = 0.35 })
})
}, { group = "demo_anim", onComplete = "done" })]],
params = [[参数说明target 指向节点;
duration 控制时长;
sequence 串行;
parallel 并行;
group/id/scope 可用于取消。
填写样例:
local move_opts = {
duration = 0.55,
id = "intro_move",
group = "intro",
scope = "dialog_1"
}
commands.move_to("actor", 220, 104, move_opts)
commands.cancel_group("intro")]],
params_en = [[Params: target points to a node;
duration controls timing;
sequence runs serially;
parallel runs together;
group/id/scope support cancellation.]],
actions = {
{ text = "动画序列", text_en = "Animate", handler = "demo_anim" },
{ text = "取消动画", text_en = "Cancel", handler = "demo_cancel" }
}
},
{
id = "widgets",
group = "Lua 表现层",
group_en = "Lua Layer",
category = "Widget",
category_en = "Widget",
menu = "组合组件",
menu_en = "Widgets",
title = "Lua Widget 组合组件",
title_en = "Lua widget composition",
summary = "Lua 组合组件仍输出普通 RuntimeNode。",
summary_en = "Lua widgets still output plain RuntimeNode tables.",
code = [[local widgets = runtime.import("runtime_widgets")
widgets.dialog("dialog", "标题", "内容", 150, 190, 420, 230, {
buttons = {
{ text = "确定", handler = "close_dialog" }
}
})]],
params = [[参数说明widgets.dialog 是 Lua helper输出普通 RuntimeNode
buttons 数组定义文案和 handler。
填写样例:
local dialog_opts = {
buttons = {
{ text = "确定", handler = "close_dialog" },
{ text = "取消", handler = "cancel_dialog" }
},
modal = true
}
widgets.dialog("dialog", "标题", "内容", 150, 190, 420, 230, dialog_opts)]],
params_en = [[Params: widgets.dialog is a Lua helper that emits plain RuntimeNodes;
buttons define labels and handlers.]],
actions = {
{ text = "打开 Dialog", text_en = "Open Dialog", handler = "demo_dialog" },
{ text = "关闭 Dialog", text_en = "Close Dialog", handler = "close_dialog" }
}
},
{
id = "audio",
group = "资源能力",
group_en = "Assets",
category = "资源",
category_en = "Assets",
menu = "资源音频",
menu_en = "Audio",
title = "资源、音效和 BGM",
title_en = "Assets, SFX and BGM",
summary = "资源 key、图片、音效、BGM 和资源组。",
summary_en = "Resource keys, images, SFX, BGM and groups.",
code = [[commands.play_sound("click", { volume = 0.8 })
commands.play_bgm("click", { channel = "demo", loop = true })
commands.preload_group("media", { failOnError = true })]],
params = [[参数说明asset/name 使用 manifest audio key
volume 范围 0~1
channel 管理 BGM
group 管理资源预载/释放。
填写样例:
commands.play_sound("click", {
volume = 0.8,
id = "click_sfx"
})
commands.play_bgm("click", {
channel = "demo",
loop = true,
volume = 0.5
})
commands.preload_group("media", { failOnError = true })]],
params_en = [[Params: asset/name use manifest audio keys;
volume is 0..1;
channel manages BGM;
group manages resource preload/evict.]],
actions = {
{ text = "音效", text_en = "SFX", handler = "demo_sound" },
{ text = "BGM 循环", text_en = "BGM loop", handler = "demo_bgm" },
{ text = "预载/释放", text_en = "Preload/evict", handler = "demo_resource" }
}
},
{
id = "spine",
group = "资源能力",
group_en = "Assets",
category = "骨骼",
category_en = "Spine",
menu = "Spine 模板",
menu_en = "Spine",
title = "Spine 接入模板",
title_en = "Spine integration template",
summary = "Spine 资源、节点和动画命令模板。",
summary_en = "Template for Spine resources, nodes and animation commands.",
code = [[-- manifest.resources
"hero_spine": {
"type": "spine",
"atlas": "assets/hero.atlas",
"skeleton": "assets/hero.skel"
}
runtime_ui.spine("hero", "hero_spine", 100, 120, 160, 220, "idle")
commands.play_spine_animation("hero", "attack", { loop = false })]],
params = [[参数说明spine 节点使用 manifest spine key
animation/skin/loop 描述播放状态;
track/queue/delay 控制动画命令。
填写样例:
runtime_ui.spine("hero", "hero_spine", 100, 120, 160, 220, "idle", {
skin = "default",
loop = true
})
commands.play_spine_animation("hero", "attack", {
track = 0,
loop = false,
queue = false,
delay = 0
})]],
params_en = [[Params: spine nodes use manifest spine keys;
animation/skin/loop describe playback;
track/queue/delay control animation commands.]],
actions = {
{ text = "播放音效", text_en = "SFX", handler = "demo_sound" },
{ text = "Toast", text_en = "Toast", handler = "demo_toast" }
}
},
{
id = "i18n",
group = "平台能力",
group_en = "Platform",
category = "本地化",
category_en = "I18N",
menu = "多语言",
menu_en = "I18N",
title = "Lua 多语言 Showcase",
title_en = "Lua-owned localization",
summary = "Lua 管理文案表、回退和语言切换。",
summary_en = "Lua owns copy tables, fallback and locale switching.",
code = [[local i18n = runtime.import("i18n")
i18n.apply_context(ctx)
runtime_ui.text("title", i18n.t("app_title"), 24, 18, 360, 34)
-- 点击按钮i18n.toggle_locale() 后更新所有文案]],
params = [[参数说明Runtime 只传 ctx.locale
Lua 自己管理 messages、fallback、刷新 Diff。
填写样例:
local messages = {
["zh-Hans"] = { app_title = "Lua Showcase" },
en = { app_title = "Lua Showcase" }
}
local locale = ctx.locale or "zh-Hans"
local text = (messages[locale] or messages["zh-Hans"]).app_title]],
params_en = [[Params: Runtime only passes ctx.locale;
Lua owns messages, fallback and refresh diffs.]],
actions = {
{ text = "切换语言", text_en = "Toggle locale", handler = "demo_i18n_toggle" },
{ text = "刷新文案", text_en = "Refresh copy", handler = "demo_i18n_refresh" }
}
},
{
id = "responsive",
group = "平台能力",
group_en = "Platform",
category = "适配",
category_en = "Layout",
menu = "分辨率适配",
menu_en = "Responsive",
title = "分辨率适配 Showcase",
title_en = "Responsive layout showcase",
summary = "设计分辨率、viewport 和布局模拟。",
summary_en = "Design size, viewport and layout simulation.",
code = [[-- manifest.display
{
"designWidth": 720,
"designHeight": 720,
"scaleMode": "fit"
}
-- ctx.screen / ctx.design / ctx.viewport
-- Lua 根据设计宽度选择 compact / desktop 布局]],
params = [[参数说明manifest.display 声明设计分辨率;
ctx.screen/design/viewport 给 Lua 做布局决策。
填写样例:
-- manifest.display
{
designWidth = 720,
designHeight = 720,
scaleMode = "fit"
}
local compact = ctx.screen.width < 640
local menu_w = compact and 220 or 320]],
params_en = [[Params: manifest.display declares design size;
ctx.screen/design/viewport let Lua make layout decisions.]],
actions = {
{ text = "手机宽度", text_en = "Phone", handler = "demo_responsive_phone" },
{ text = "平板宽度", text_en = "Tablet", handler = "demo_responsive_tablet" },
{ text = "桌面宽度", text_en = "Desktop", handler = "demo_responsive_desktop" }
}
}
}
---@return ShowcaseExample[]
function examples.all()
return examples.items
end
---@param id string
---@return ShowcaseExample
function examples.find(id)
for _, example in ipairs(examples.items) do
if example.id == id then
return example
end
end
return examples.items[1]
end
return examples