Layout helpers, регистрация экранов и основной цикл.
Страница повторяет разделы API.md про layout helpers, экраны, цикл, input model, redraw и transitions.
6. Layout helpers
Это лёгкие helper-ы для раскладки UI без тяжёлой layout-системы.
Базовые типы:
UiSize size{120, 40};
UiRect rect{0, 0, 240, 320};
UiInsets insets{10, 10, 10, 10};
6.1. Slicing API
UiRect root{0, 0, 240, 320};
UiRect work = inset(root, 10);
UiRect header = takeTop(work, 24, 8);
UiRect footer = takeBottom(work, 28, 8);
UiRect content = work;
Доступно:
inset(rect, all)inset(rect, l, t, r, b)inset(rect, UiInsets{...})takeTop(...)takeBottom(...)takeLeft(...)takeRight(...)placeInside(...)centerIn(...)
6.2. Flow API
UiSize sizes[3] = {{40, 20}, {60, 20}, {40, 20}};
UiRect out[3];
flowRow(area, sizes, out, 3, 10, Center, Center);
flowColumn(area, sizes, out, 3, 8, Center, Center);
Для распределения доступны:
StartCenterEndlayout::SpaceBetweenlayout::SpaceEvenly
6.3. Cursor-based API
UiFlowRow<3> row(area, 10, layout::SpaceEvenly, Center);
row.next(40, 24);
row.next(60, 24);
row.next(40, 24);
row.finish();
Аналогично работает UiFlowColumn<N>.
Как этим пользоваться правильно:
next(w, h)резервирует следующий slot- после всех
next(...)нужно вызватьfinish() - итоговые прямоугольники потом берутся через
row[i]илиcolumn[i]
Для позиционирования и выравнивания часто используются короткие шорткаты:
centerдля автоматического центрирования по осиLeft,Center,RightTop,Bottom
11. Экраны и цикл
11.1. Регистрация экранов
Экраны регистрируются через макрос SCREEN(name, order):
SCREEN(ScreenHome, 0)
{
ui.clear(ui.rgb(0, 0, 0));
}
SCREEN(ScreenSettings, 1)
{
ui.clear(ui.rgb(8, 8, 8));
}
Что создаёт макрос:
- callback-функцию экрана;
- числовой id экрана;
- автоматическую регистрацию экрана в таблице GUI.
Что важно:
nameстановится константой id, её потом можно передавать вsetScreen(...),updateList(...),updateTile(...)и другие APIorderзадаёт порядок регистрации экранаorderдолжен быть уникальным для каждого экрана- обычно первый экран делают с
order = 0
После этого экран можно активировать:
ui.setScreen(ScreenHome);
11.2. Основной цикл
Базовый вариант:
void loop()
{
ui.loop();
}
Вспомогательный вариант, если есть две кнопки Button:
Button Next(1, Pullup);
Button Prev(2, Pullup);
void setup()
{
Next.begin();
Prev.begin();
}
void loop()
{
ui.loopWithInput(Next, Prev);
}
Вариант с тремя кнопками (Next/Prev/Select):
Button Next(1, Pullup);
Button Prev(2, Pullup);
Button Select(3, Pullup);
void setup()
{
Next.begin();
Prev.begin();
Select.begin();
}
void loop()
{
ui.loopWithInput(Next, Prev, Select);
}
loopWithInput(...) обновляет объекты Button, обрабатывает ввод для built-in overlay/меню (list/tile/popup/error/notification) и затем вызывает ui.loop(). Если вам нужен свой state-machine ввода, используйте pollInput(...) и/или передавайте состояния кнопок вручную через ...Input() fluent-методы.
По умолчанию loopWithInput(...) включает авто-переходы между экранами по коротким нажатиям Next/Prev (когда не активны overlay/меню). loopWithPolledInput() обрабатывает built-in overlay/меню на основании последнего pollInput(...) и так же включает авто-переходы между экранами по коротким нажатиям Next/Prev (как loopWithInput(...)). Чтобы отключить авто-навигацию на текущем тике (если вы используете кнопки под свой сценарий), вызовите ui.consumeAutoNav() до loopWithPolledInput().
Если loopWithInput(...) не используется, вызывайте btn.update() сами в начале каждого loop(). После этого wasPressed() и isDown() читают уже обновлённое состояние кнопки.
Если нужен готовый snapshot ввода для собственного state-machine:
InputState input = ui.pollInput(Next, Prev);
или (если есть кнопка выбора):
InputState input = ui.pollInput(Next, Prev, Select);
pollInput(...) сам обновляет кнопки и возвращает готовый снимок их состояния на текущий тик.
Поля InputState:
nextDown- кнопкаNextсейчас удерживаетсяprevDown- кнопкаPrevсейчас удерживаетсяnextPressed- кнопкаNextбыла нажата именно в этом тикеprevPressed- кнопкаPrevбыла нажата именно в этом тикеselectDown- кнопкаSelectсейчас удерживается (если включен 3-button режим)selectPressed- кнопкаSelectбыла нажата именно в этом тике (если включен 3-button режим)comboDown- обе кнопки сейчас зажаты одновременноhasSelect- true, еслиpollInput/loopWithInputвызваны в 3-button режиме
Разница простая:
Down- состояние удержанияPressed- одноразовое событие нажатия
11.2.1. Где библиотека использует кнопки (шорткаты и встроенные сценарии)
Если вы используете loopWithInput(...) или вручную прокидываете ...Input() fluent-методы, то кнопки обрабатываются в этих местах:
- Скриншоты (built-in shortcut): удержание
Next + Prev(если включены screenshots) — захват скриншота. - List menu (
updateList): Next/Prevкоротко — перемещение по пунктам.- 2-button режим: удержание
Next— открытьtargetScreen. - 3-button режим: короткое нажатие
Select— открытьtargetScreen. - удержание
Prev—backScreen()(назад по history). - Tile menu (
updateTile): то же самое, что и list (перемещениеNext/Prev, открытьNext-holdилиSelect-press, назадPrev-hold). - Popup menu:
Next/Prev— перемещение; 2-button ?????:Next-holdподтверждает; 3-button ?????:Select-pressподтверждает;Prev-holdзакрывает. - Notification overlay: закрывается через встроенную обработку ввода:
- 2-button режим:
Prevподтверждает/закрывает. - 3-button режим:
Selectподтверждает/закрывает (иPrevтоже принимается для совместимости). - Error overlay:
Next/Prevпереключают ошибки; комбинация (comboDown) используется для подтверждения/закрытия (зависит от типа ошибки). - Slider:
Next/Prevдвигают значение (берётся из последнегоpollInput(...)). - Graph pause (только 3-button режим):
Selectна экранах с графиком переключает паузу (см. раздел 15.4). - Auto screen-nav: при использовании
loopWithInput(...)короткиеNext/Prevпереключают экраны черезnextScreen()/prevScreen()когда не активны overlay/меню.
Если вы используете Next/Prev под кастомную логику на каком-то экране (и не хотите авто-переключения экранов), после своей обработки вызовите:
ui.consumeAutoNav();
11.3. Управление экранами
Эти методы управляют активным экраном и переходами между экранами.
ui.setScreen(ScreenHome); // сразу переключает на указанный экран
ui.currentScreen(); // возвращает id текущего активного экрана
ui.nextScreen(); // переходит на следующий экран по порядку регистрации
ui.prevScreen(); // переходит на предыдущий экран по порядку регистрации (циклически)
ui.backScreen(); // возвращает назад по navigation-history
ui.screenTransitionActive(); // показывает, что переход между экранами сейчас ещё идёт
Что важно:
- библиотека сама ведёт history переходов между экранами (для
backScreen()) - если экран меняется через
setScreen(...), текущий экран добавляется в history автоматически
11.4. Принудительная перерисовка
ui.requestRedraw();
Нужно, когда данные экрана изменились вне обычного render-flow, и вы хотите гарантированно перерисовать следующий кадр.
11.5. Анимация переходов
ui.setScreenAnim(SlideX, 250);
setScreenAnim(mode, durationMs) задаёт стиль и длительность перехода между экранами.
Доступные режимы:
None- переход без анимацииSlideX- горизонтальный слайдSlideY- вертикальный слайд