IconView and ListView / 图标与列表菜单

IconViewListView 都是完整的 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;
};

IconItemListetl::vector<IconItem, MAX_ICONVIEW_ITEMS>titlebitmapuserData 都是非拥有指针,不要指向短寿命局部数据。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 {
// 从存储中读取到 ListItemExtra 指向的状态。
}

void onSave() override {
// 把已更改状态写回存储。
}
};
1
2
3
4
5
6
7
8
bool soundEnabled = true;
int32_t brightness = 60;

ListItem items[] = {
{.title = "Sound", .extra = {.switchValue = &soundEnabled}},
{.title = "Brightness", .extra = {.intValue = &brightness}},
{.title = "About", .pFunc = []() { open_about(); }},
};

ListItem 还可以用 nextList + nextListLength 指向子菜单。历史栈最大深度由 PIXELUI_MAX_LISTVIEW_DEPTH 限制。所有 ListItem、子列表、title 内容以及 extra 指针指向的数据都必须比 ListView 活得更久。

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

ListView 当前的列表数组 API 仍然较低层,使用前建议先参考主仓库 examples/ListViewDemo1.cpp。长度必须大于 0,不要用空数组构造它。

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