IconView and ListView / 图标与列表菜单

IconView 和 ListView 都是完整的 IApplication,不是需要放进另一个 App 里的 Widget。

IconView

IconView 适合少量带 XBM 图标的项目。下面用一个具体派生类提供配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ToolMenu final : public IconView {
public:
ToolMenu(PixelUI& ui, void*) : IconView(ui) {
IconItemList items;
items.emplace_back("Clock", clockBits, nullptr);
items.emplace_back("Counter", counterBits, nullptr);
setItems(items);
setTitle("< Tools >");
enableProgressBar(true);
enableStatusText(true);
enableSelectedItemTitle(true);

setSelectionCallback([this](int index, const IconItem&) {
selected_ = index;
});
}

private:
int selected_ = 0;
};

IconItemList 是 etl::vector<IconItem, MAX_ICONVIEW_ITEMS>。title、bitmap 和 userData 都是非拥有指针,不要指向短寿命局部数据。AppLauncher 就是 IconView 的一个现成用法。

IconView 的三个可见槽位、selector、滚动和进度条都根据 getDisplayWidth() / getDisplayHeight() 用整数公式计算,不再绑定 128x64 显示尺寸。状态文本使用共用的定长 buffer 整数 writer 拼接。

ListView

ListView 适合设置项、布尔开关、整数值和多级子菜单。它是抽象类,派生类必须实现 onLoad() 和 onSave():

1
2
3
4
5
6
7
8
9
10
11
12
13
class SettingsView final : public ListView {
public:
SettingsView(PixelUI& ui, ListItem* items, int count)
: ListView(ui, items, count) {}

void onLoad() override {
// 从存储中读取状态。
}

void onSave() override {
// 把已更改状态写回存储。
}
};
1
2
3
4
5
6
7
8
9
10
11
12
bool soundEnabled = true;
bool notificationsEnabled = false;
int32_t brightness = 60;
char modeText[] = "Auto";

ListItem items[] = {
{.title = "Sound", .accessory = ListItemAccessory::toggle(soundEnabled)},
{.title = "Notifications", .accessory = ListItemAccessory::check(notificationsEnabled)},
{.title = "Brightness", .accessory = ListItemAccessory::value(PixelUIValue::Binding::integer(brightness))},
{.title = "Mode", .accessory = ListItemAccessory::text(modeText)},
{.title = "About", .pFunc = []() { open_about(); }},
};

ListItem 还可以用 nextList + nextListLength 指向子菜单。历史栈最大深度由 PIXELUI_MAX_LISTVIEW_DEPTH 限制。所有 ListItem、子列表、title 内容、accessory 目标和回调捕获的对象都必须比 ListView 活得更久。toggle() 允许列表直接修改布尔值;check() 只显示状态,修改逻辑由项目回调负责;value() 使用 PixelUIValue::Binding 格式化数值。

ListView 最多只保存一个当前 switch 动画,并用稳定的 ListItem* 标识它,而不是按行号保存每行状态;非活动 switch 的位置直接由 bool 值推导。因此父菜单和子菜单即使有相同行号,也不会共享动画状态。列表数组不仅要活得足够久,地址也必须保持稳定。

选中项目的长标题会在可用宽度不足时自动滚动,accessory 会占用右侧布局空间。列表数组 API 要求调用者提供稳定存储:长度必须大于 0,数组地址、标题和 accessory 目标在整个 ListView 生命周期内都不能改变。

avatar
Link0327
汪🐱me0w, but furry wolf. 尝试变得毛茸茸
Link's Github
最新文章
网站信息
文章数目 :
3
本站访客数 :
本站总浏览量 :
最后更新时间 :