Представьте: пользователь со слабым зрением увеличивает шрифт на Android до 1.6x или даже 2.0x, а ваше приложение превращается в кашу — тексты налезают друг на друга, кнопки перемещаются или исчезают. Мы сталкивались с этим десятки раз. Типичный случай: Samsung Galaxy S10, масштаб 1.6x — в карточке заказа текст обрезан наполовину, кнопка «Оплатить» недоступна. Причина? Фиксированные высоты контейнеров и использование dp вместо sp. После нашего аудита и доработки (замена layout, тесты) приложение выдержало fontScale 2.0 без единой поломки.
Android позволяет изменять масштаб шрифта в Settings → Display → Font Size. Диапазон: от 0.85x до 2.0x (на стоковом Android). На Samsung One UI — до 1.6x в стандартном UI, но fontScale в Configuration может достигать 2.0x. Единицы sp масштабируются, dp — нет. Игнорирование этого — главная причина проблем с доступностью.
Почему нужен аудит масштабирования шрифтов?
Без аудита вы рискуете оттолкнуть 15-20% пользователей, которые меняют масштаб. Например, по статистике Google, 1 из 8 людей имеет ослабленное зрение. Кроме того, Google Play Store требует соблюдения доступности; нарушение может привести к отклонению обновлений.
Мы провели более 50 проектов по адаптации под крупные шрифты на Android. В нашей практике был клиент — агрегатор такси — потерявший 30% конверсии на экране заказа из-за того, что пользователи с масштабом 1.4x не могли прочитать время прибытия. Мы исправили layout за 3 дня, и конверсия восстановилась.
Как правильно использовать sp и dp?
android:textSize="16sp" — корректно, шрифт масштабируется. android:textSize="16dp" — не масштабируется. Хардкод в dp — одна из самых частых ошибок. В Compose: fontSize = 16.sp — масштабируется, fontSize = 16.dp — Lint выдаст ошибку компиляции начиная с Compose 1.3. Однако TextUnit.Unspecified в кастомных компонентах — снова проблема.
| Единица | Масштабируется | Рекомендация |
|---|---|---|
| sp | Да | Использовать для текста |
| dp | Нет | Для отступов, размеров не текста |
В чём отличие? При fontScale 2.0 16sp превращается в 32sp (пиксели удваиваются), а 16dp остаётся 16dp. Если вы задали высоту контейнера в dp, текст вылезет наружу. Сравните: wrap_content адаптируется к любому масштабу, тогда как фиксированная высота ломается при fontScale 1.6 уже в 80% случаев.
Почему фиксированная высота контейнеров — проблема?
Самая частая ошибка: android:layout_height="48dp" на TextView или контейнере с текстом. При fontScale = 2.0 текст размером 16sp занимает ~64dp высоты. Контейнер в 48dp обрезает содержимое. Правильное решение: wrap_content для высоты всех текстовых элементов. Для ConstraintLayout — убрать фиксированную высоту у цепочек с текстом.
minHeight можно оставить для touch target (минимум 48dp по Material Design) — но только через minHeight, не height.
Строки с вставками
String.format("Вы заработали %d очков", points) — при длинном числе строка удлиняется. Но проблема не в числе, а в фиксированном layout вокруг. ConstraintLayout с wrap_content справляется; вложенные LinearLayout с gravity — нет.
Compose: LocalDensity и масштаб
В Jetpack Compose LocalDensity содержит и density (DPI), и fontScale. Если вручную конвертировать размеры через density.density без учёта fontScale — кастомные компоненты с TextUnit-расчётами не масштабируются.
with(LocalDensity.current) { 16.sp.toPx() } — возвращает пиксели уже с учётом fontScale. Если используете это значение как высоту Canvas — всё хорошо. Если игнорируете и задаёте фиксированный height в Modifier — нет.
Как локально отключить масштабирование для декоративных элементов?
Для декоративных элементов в Compose можно использовать CompositionLocalProvider(LocalDensity provides density), где density — копия с fontScale = 1f. Это полезно для логотипов или иконок, которые не должны меняться. Однако применяйте осторожно: пользователь ожидает, что весь интерфейс масштабируется.
Наш опыт: кейс с масштабированием 2.0
Из нашей практики: клиент-агрегатор такси. При масштабе шрифта 1.6x на популярных моделях тексты в карточке водителя налезали друг на друга. Мы диагностировали проблему: все LinearLayout внутри ScrollView имели фиксированную высоту. Заменили их на ConstraintLayout с wrap_content, а для touch target оставили minHeight. Результат — приложение прошло тесты при fontScale 2.0. Сравнение: до доработки текст обрезался на 50%, после — полностью читаем.
Как мы тестируем масштабирование?
Используем пошаговый подход:
- Устанавливаем fontScale 2.0 через ADB:
adb shell settings put system font_scale 2.0. - Визуально проверяем каждый экран на предмет перекрытий и обрезания.
- Запускаем Espresso snapshot-тесты с
Configuration.fontScale = 2fдля автоматической регрессии.
Android Studio Device Emulator: Pixel 6 с fontScale 2.0 — первый стенд. Реальный Samsung с One UI — второй стенд, там поведение отличается.
| Инструмент | Метод | Особенности |
|---|---|---|
| ADB | settings put system font_scale 2.0 | Быстро, без перезапуска |
| Espresso | Configuration.fontScale = 2f | Для автоматических тестов |
| Физическое устройство | Настройки → Шрифт | Реалистичный сценарий |
Что входит в услугу?
- Аудит экранов на корректное масштабирование (проверка sp/dp, высот контейнеров, вставок)
- Исправление layout: замена фиксированных высот на wrap_content, оптимизация ConstraintLayout
- Для Compose: коррекция LocalDensity, локальное отключение масштаба для декоративных элементов
- Настройка тестов: ADB-скрипты и Espresso snapshot-тесты
- Документация по поддерживаемым экранам и ограничениям
- Гарантия: после доработки приложение корректно отображается при fontScale от 0.85 до 2.0
Сроки и стоимость
Срок: от 2 до 3 дней на типовое приложение (10–20 экранов). Стоимость рассчитывается индивидуально. Закажите аудит поддержки масштабирования шрифтов — обеспечим удобство для пользователей с ослабленным зрением. Получите консультацию и коммерческое предложение. Наш аудит помогает сэкономить бюджет на переработку после отклонения в маркете.







