VEU.WathBody/1-docs/4-modules/m13-fenix-data-field/api_specs/03-screen.md

5.3 KiB
Raw Blame History

Спецификация 03: экран поля — макет и отрисовка

Источники: module_reqs разд. 1 (единица 5) и 2, Ф-2.1/Ф-2.2 (с errata), ui-ux разд. 2 (glanceable, цвет дублируется текстом), tech-req 6 п. 1. Единица 5.

1. Макет (resources\layouts\layout.xml)

Параметрический макет семейства квадратных MIP-экранов — якоря (loc="center" и верх/низ), без единой фиксированной координаты: позиции и шрифты вычисляются от dc.getWidth()/getHeight() в onLayout. Один макет на всё семейство (fenix6x 280×280, fenix6 260×260, fenix6s 240×240 — добавление таргета без правок, инвариант 5).

Элементы (сверху вниз):

Элемент Содержимое Шрифт
zoneLbl подпись зоны + цветная плашка-ободок FONT_TINY
hrLbl текущий пульс или «—» FONT_NUMBER_LARGE (запасной FONT_NUMBER_MEDIUM — §3)
unitLbl «уд/мин» FONT_TINY
stateLbl «ОТДЫХ mm:ss» / «ПОДХОД mm:сс · ср N» FONT_SMALL

2. Содержимое и цвета

  • фон — чёрный (COLOR_BLACK), текст — белый; MIP, читаемость на солнце без подсветки;
  • зона: плашка/ободок цвета зоны (COLOR_BLUE/GREEN/YELLOW/RED по ZoneCalc) вокруг подписи зоны; подпись текстом — цвет не единственный носитель (ui-ux): «восстановление»/«лёгкая»/ «средняя»/«высокая»; нет пульса → NONE: серая плашка (COLOR_DK_GRAY), подпись «—»;
  • пульс: крупное число currentHeartRate; null → «—» (unitLbl гасится);
  • строка состояния:
    • идёт отдых (RestTimer.isResting) → «ОТДЫХ 1:48» — обратный отсчёт остатка (mm:сс, при остатке ≥ 10 мин «мм:сс» с ведущими разрядами не рвётся — формат m:ss/mm:ss);
    • иначе → «ПОДХОД 2:05 · ср 132»: SetTracker.elapsedMs (время с последнего Lap — errata Ф-2.1) и SetTracker.avgBpm; среднее null → «ср —»;
  • форматирование времени — чистая функция mmss(ms) (округление вниз до секунд; часы не нужны — интервалы < 10 мин).

3. Шрифт пульса (адаптивный)

onLayout: берётся FONT_NUMBER_LARGE; если высота глифов + прочих элементов не влезает в высоту области (мелкие страницы данных, 2+ поля на странице) — шаг вниз до FONT_NUMBER_MEDIUM. Пульс — главное число экрана (Ф-2.1: шрифт пульса максимальный из доступных на области).

4. Класс FenixDataField (связка)

  • initialize(): создание ядра (SetTracker/RestTimer/ZoneCalc/ Vibe/FieldSettings), начальное состояние — «нет данных» (переменные инициализируются здесь, не в compute — асинхронность compute/onUpdate по документации);
  • compute(info): раз в секунду — currentHeartRate → SetTracker.onSample, кэш пульса; RestTimer.onEnd(timerTime) → лёгкая вибрация; Vibe.onZone(zone, timerTime) → двойная при красной (гистерезис);
  • onTimerLap(): SetTracker.onLap + RestTimer.start — Lap = конец подхода = старт отдыха (errata Ф-2.3);
  • onTimerStart/Reset: SetTracker к нулю, RestTimer не активен;
  • onUpdate(dc): отрисовка по кэшу (§2); данные могли ещё не прийти — рисуем прочерки;
  • onTimerPause/Resume: без кода — timerTime стоит/идёт, таймеры замирают сами (спека 02 §3).

5. Симуляторный смок (критерий приёмки 2, шаг 3)

  1. Поле добавляется в профиль Strength симулятора, отображается без ошибок отрисовки;
  2. симуляция пульса: число обновляется ≈1/с, плашка зоны и подпись соответствуют порогам (прогнать пульс через все 4 зоны);
  3. Lap (симулятор): метрики обнуляются, строка «ОТДЫХ …» тикает вниз, по нулю — однократная вибрация (лог симулятора);
  4. пульс в красной зоне — двойная вибрация, повтор не чаще 60 с;
  5. пауза активности — отсчёты стоят; resume — продолжаются;
  6. нулевой/отсутствующий пульс — «—», поле живое (не падает).