По любви · Android × Figma · 11.09.2026

Оплата, симпатии, записки и переписка сошлись с макетом

Десять экранов второй половины приложения — от экрана «подписка оформлена» до контекстного меню сообщения — собраны из данных нод: переменных, стилей, матриц поворота, контуров форм и эффектов. Каждый кадр снят на устройстве в честном масштабе ×3 (1170×2532) и сведён с рендером Figma; кадры выше экрана — по частям с прокруткой. Ниже кадр рядом с рендером, четыре числа на кадр и разбор того, что оказалось не так. Главная находка партии — размытие фотографии размывает и её прозрачность: край карточки становится полупрозрачным, сквозь него видно фон, и поточечной подгонкой цвета это было не закрыть. Вторая по важности не про вёрстку, а про меру: число, по которому мы закрываем кадр, не видит блок, которого нет вовсе. Это продолжение артефактов по кадрам S01–S10, S11–S20, S21–S30 и S31–S40.

97 / 98кадров с зелёной геометрией при пороге 0,3 %
0,000 %лучшая геометрия
0,273 %худшая среди закрытых
116замеров с частями прокрутки
7новых экранов собрано с нуля
37ловушек найдено и записано

Смотровая

Кадр рядом с рендером

Тяните шторку, чтобы совместить макет и приложение. «Карта» показывает, где остаётся расхождение по геометрии: синим закрыты системный статус-бар, полоска home, клавиатура и диалоги разрешений iOS — их рисует Android, они в сравнении не участвуют (спека 6.4).

Рендер кадра из Figma Снимок экрана приложения

Числа

Четыре измерения на кадр

Полное — доля пикселей, отличающихся сильнее ΔE 6 вне масок. Без текста — то же с исключёнными текстовыми блоками. ±1 px — пиксель считается расхождением, только если не совпал ни с одним пикселем рендера в окне ±1: сдвиг растра на долю пикселя не есть ошибка вёрстки. Геометрия — два последних вместе, то есть чистая форма, положение и материал; по ней и выносится вердикт. Шкала показывает геометрию относительно порога 0,3 %.

ЭкранКадрСостояние Полное %Без текста % ±1 px %Геометрия % Шкала до порога 0,3 %

Разбор

Что оказалось не так

Каждая строка — расхождение из реестра ловушек спеки: что показала нода, что делало приложение и сколько это стоило в числах.

Размытие размывает и прозрачность, а не только цвет

На кадрах «нет подписки» фотография размыта радиусом 50. Эффект стоит не на прямоугольной обрезке, а на самом векторе формы — значит размывается уже обрезанный формой слой вместе с его альфой, а начисто край режет маска-близнец уже после размытия. У кромки альфа падает, сквозь неё виден белый фон — и рендер там светлее самой фотографии: в точке (60, 608) он 162,160,157 при фотографии 23,21,24. Размытая прямоугольная обрезка давала там 26,23,20, и никакой подбор цвета этого не закрывал. Теперь растр готовится в RGBA: маска формы, размытие в помноженном на альфу виде, обрезка формой в Compose.

−9,0 п.п.кадр 8641:19001
9,107 % → 0,079 %

У повёрнутой плашки из ноды берётся точка поворота, а не край габарита

Плашка имени на карточке симпатии — HUG по содержимому, и её габарит в ответе API посчитан по старой ширине: 216 при настоящих 238…246. Плашка растёт в ту сторону, куда её не прижали, и вместе с ней уезжает точка поворота — на Δ·(cos, sin). Какой край габарита при этом неподвижен, зависит от знака угла: при +5° правый и нижний, при −5° правый и верхний. Прежняя привязка «верх габарита» держала только второй случай: у кадра 8425:23698 рендер рисует плашку на 2,7 dp выше числа ноды.

−0,59 п.п.хвост 8511-32824
0,670 % → 0,083 %

Заливка картинкой кроет габарит вектора, а не карточки

У пятой брендовой формы контур кончается на 278 из 280 единиц вьюпорта: габарит вектора 366,01×413,62 при карточке 366,01×416,60. scaleMode = FILL кроет именно вектор, поэтому фотография в такой карточке на 0,7 % мельче остальных. Растянутая на всю карточку, она уезжает вниз тем сильнее, чем ниже смотреть: +1 px на 300 dp глубины и +8 px на 600.

−1,6 п.п.хвост 8090-17420
1,854 % → 0,233 %

Размытие под контекстным меню — это размытие самого экрана

Под меню сообщения у ноды стоит BACKGROUND_BLUR: размывается всё, что под ним, а не отдельная подложка. Modifier.blur на эмуляторе молчит, поэтому экран снимается вторым кадром без меню, размывается на приборе с σ = радиус × 0,410 в пикселях снимка (×3) и кладётся картинкой. Там же выяснилось, что затемнение рисует сам прямоугольник размытия, а не шторка поверх: вторая тень делала подложку втрое темнее — 16 единиц вместо 102 на белом.

−1,5 п.п.кадр 16970:47336
1,53 % → 0,151 %

Ссылку Figma рвёт не там, где Compose

Compose держит URL одним словом и переносит его целиком, а Figma рвёт после косой, дефиса и вопроса — но не внутри :// и не после =. В текст ставятся нулевые пробелы ровно в этих местах: чернила по кадру сошлись с −15 % до +0,03 %. Правило выведено на четырёх кадрах со ссылками и проверено на пятом, где ссылка процент-кодирована.

−15 п.п. чернилкадр 16970:47309
перенос по правилу ноды

Рамка пузыря переписки бывает от прошлой раскладки

У половины пузырей размер в ответе API остался размером мастера — 141×44 или 159×44, — потому что авто-лейаут не пересчитан. Рамка считается по правилу самого авто-лейаута там, где ответ её не пересчитал, и берётся из ноды там, где пересчитал; правило проверено на пяти кадрах с посчитанной рамкой. Заодно из-за этого маска текста в мере вставала не на своё место — настоящие рамки теперь пишутся отдельным файлом и читаются и мерой расхождений, и мерой текста.

0,7…0,9 → 0,09 %28 кадров переписки
правило вместо числа

Пунктирная обводка в ответе API — это контур штрихов, а не линия

Два сердца пунктиром на пустом экране чатов выходили вдвое толще: обводить strokeGeometry пунктира нельзя — это уже готовый контур штрихов, и обводка его удваивает. Штрихи режутся по средней линии из vectorNetwork и dashPattern: чернила 2037 dp² против 713 стали 713.

×2,9 чернилpic_chats_empty_hearts
резчик пунктира

У одной и той же плашки имени три мастера с разной типографикой

Первый — имя 18/22, второй — 18/24, третий — 18/24 в две строки (48) и с прижатым к нижней строке возрастом. Высоту самой плашки держит возраст, поэтому ошибка в межстрочном интервале имени по высоте плашки не видна — только по месту строк.

−0,86 п.п.хвост 8090-17420
0,952 % → 0,090 %

Затемнение поверх размытия есть не у каждой карточки

Чёрная заливка 35 % стоит только у первой карточки кадра; у трёх остальных того же кадра и у всех четырёх соседнего её нет. Правило «есть размытие — значит есть затемнение» красило карточки на 38 единиц канала темнее. Признак берётся из ноды: полупрозрачный вектор со сплошной заливкой во всю карточку — у силуэта-заглушки свои полупрозрачные эллипсы той же кисти, и они меньше карточки.

38 единиц канала8641:19001 · 8425:23680
затемнение из ноды

Белая подложка, которой нет в ноде

Под кнопкой «Узнай, кто поставил лайк» стояла белая полоса — в ноде у этого блока заливки нет вовсе. На снимке ровно с 689 dp начиналась белизна, а в рендере там видна размытая фотография и над кнопкой, и под ней.

390×72button-stack 8641:19026
заливка убрана

Мера

Чего не видит «геометрия»

Число, по которому мы закрываем кадр, считает форму и материал, но исключает текстовые блоки — иначе в него попадала бы разница отрисовки букв. Значит, ошибку в самом тексте оно не поймает. В этой партии из-за этого дважды стоял зелёный вердикт на кадре с настоящей ошибкой. Обе нашла отдельная мера — плотность чернил по каждому блоку.

Блока не было вовсе — а «геометрия» показывала 0,112 %

Заголовок секции «Записки» с числом искался в раскладке по списку guid, и список промахнулся мимо двух кадров: на них заголовка просто не рисовалось. Метрика молчала — текст в ней замаскирован. Мера чернил показала у блока ноль при полных в рендере и −13,3 % по кадру. Узлы теперь ищутся по признаку, а не по списку.

−13,3 % чернил8090:17420 · 8425:23680
при зелёной геометрии

Непрочитанная строка чата набрана другим кеглем и цветом

Найдено уже после того, как десяток был закрыт, — той же мерой при повторной проверке. У непрочитанной строки текст сообщения чёрный и набран Manrope 16/20 с треком 0,2, а у прочитанных — Beigeish Black 14/18 с треком 0,1. Строка от этого шире на 30 dp. Геометрия кадра — 0,205 %, зелёная.

−7,2 → −2,3 %кадр 16986:53790
цвет и кегль из ноды

Кадр выше экрана без записанной части не мерится вовсе

Высокие кадры снимаются частями с прокруткой. Если части не записать, нижняя полоса кадра не сверяется ни разу — и об этом ничто не сообщает. Так у кадра «no subscription» в 3140 dp не было снято ни одного кадра, а у «skeleton» в 1082 не проверялись нижние 238. Теперь есть проверка: пройтись по рендерам выше экрана и убедиться, что для каждого есть снимок с прокруткой не меньше «высота − 844».

+5 замеров8425:23680 · 8154:3994 · 8722:35978
0,000…0,112 %

Один и тот же кадр в двух раскладках — молчаливая подмена

Карты кадров складываются, и побеждает поздняя. Нашлось три случая: кадр «pagination» собирался и как симпатии, и как записки; кадр анкеты со всеми частями был записан дважды подряд; четыре кадра состояний генератор писал в один файл, а рисовал другой — из-за этого часть высокого кадра уехала к заготовке без полос скелета. Теперь есть проверка на повторы ключей по всем файлам раскладки.

−5,7 п.п.хвост 8154-3994
5,861 % → 0,198 %

Собрано

Семь новых экранов

Кроме состояний уже готовых экранов, в этой партии впервые собраны семь больших экранов целиком — из нод, а не с картинки.

Переписка — 42 кадра на один экран

Шапка пары с фотографией в повёрнутой рамке-зеркале, пузыри с хвостами и цитатами, разделители дат, кружки догрузки сверху и снизу, панель ответа и правки, ссылки с подчёркиванием своим цветом, контекстное меню поверх размытого экрана, снеки. Один файл закрывает сразу два реестра — переписку и контекстное меню.

0,000…0,256 %42 кадра
Чаты · V3 · V5

Таб «Симпатии» — карточки под углом

Пять карточек, у каждой своя брендовая форма, свой поворот 5…15° и своя плашка имени — тоже повёрнутая и тоже по содержимому. Плюс карусель записок из двух плашек под углом и белой карточки, шесть состояний прокрутки, скелет, два пустых состояния, ошибка и два кадра с размытыми фотографиями.

0,000…0,233 %14 кадров, 22 замера
8 частей прокрутки

Таб «Чаты» и список пар

Карусель взаимных симпатий с формами, строки переписок со счётчиками, значками «проверен» и «подписка», галочками «прочитано» и состоянием «Печатает» из трёх гаснущих точек; скелеты, пагинация, снек ошибки и плашка правил сообщества. Рядом — список пар V3 с теми же формами.

0,000…0,284 %17 кадров
Чаты · V3 · V4

Оплата, настройки подписки и записки

Три шторки поверх пейволла и три тёмных экрана «подписка оформлена» с фоном, посчитанным из ноды; настройки с ячейками продления и экран подписки в профиле; список записок с карточками загрузки и снеком ошибки.

0,000…0,134 %21 кадр
4 экрана

Вопросы

Что стоит посмотреть в макете

Здесь не ошибки вёрстки, а места, где макет спорит сам с собой или с собственным рендером. Мы делаем как в рендере и передаём пару дизайнеру.

ЧтоГдеКак сейчас
Число записок в заголовке8090:17432 на трёх кадрах чёрное, на шести — Beigeish Gray; блок и кегль те же
Затемнение поверх размытой фотографии8555:43502 стоит у первой карточки кадра и отсутствует у трёх остальных и у всех четырёх соседнего кадра
Контур пятой брендовой формы2788:7837 кончается на 278 из 280 единиц вьюпорта — фотография в такой карточке на 0,7 % мельче, чем в остальных четырёх
Заголовок секции «Записки»8154:3994 · 13944:1830 на одном кадре лежит на y=170, на другом — на 190 при одинаковой шапке
Кадр V4 «scroll»13353:33007 в ноде стоит прозрачность 0,01 (приглушённая копия на странице), и рендер выгружен с альфой 3/255 — сравнивать нечем
Карточка контекстного меню16983:52863 скруглений в ноде нет вовсе, а рендер рисует скруглённую карточку
Строка списка пар V311404:26427 блок имени 241 dp во всю рамку, и значок «проверен» на x=314 попадает внутрь него
Блок текста поля ввода7647:27244 стоит на y=710 при поле 698…802, а рендер прижимает текст к низу поля

Границы

Что не закрыто

Форма зелёная — это половина работы. Вот честный остаток.

ЧтоПочемуЧто нужно
Кадр 13353:33007 — 8,61 % единственный кадр десятка, форма которого не доказана числом: в ноде стоит прозрачность 0,01, и рендер ×3 выгружен с альфой 3/255 — в нём 34 значения канала на весь кадр перевыгрузить кадр из Figma без приглушения; пока сверен глазами по цветовому каналу
Поведение всех десяти экранов трасса запросов против карт Flutter не снята ни по одному экрану файловый лог запросов в debug-сборке и инструмент разбора
Два текстовых остатка на одном кадре процент-кодированная ссылка переносится на знак раньше рендера (−32,9 % чернил), на другом текст в поле правки виден на строку короче (−10,4 %); геометрия у обоих зелёная разобрать метрики шрифта и обрезку блока полем ввода
Экраны в приложении все семь собраны и снимаются раскладкой, но в навигацию не включены заменить прежние экраны и переснять кадры
Сплошная проверка чернил по блокам именно она нашла две ошибки при зелёной геометрии — и прогнана пока точечно, а не по всем 356 кадрам проекта прогнать по всему проекту; вердикт хуже 10 % сейчас у пяти кадров, из них два вне этого десятка не разбирались
Низ четырёх высоких кадров прошлых десятков у них не записаны части прокрутки — нижняя полоса не сверялась ни разу добавить части и переснять: 1349:13058, 1601:18880, 2998:14491, 3342:8104