Реализуйте жесты масштабирования «щипок-зум» для поддержки масштабируемого контента в вашем приложении. Это стандартный, совместимый с платформой метод улучшения доступности, позволяющий пользователям интуитивно настраивать размер текста и элементов пользовательского интерфейса в соответствии со своими потребностями. Ваше приложение может настраивать пользовательское поведение масштабирования с помощью детального управления и контекстного поведения, что обеспечивает пользователям удобство, которое часто усваивается быстрее, чем системные функции, такие как увеличение экрана.
Выберите стратегию масштабирования
Стратегии, описанные в этом руководстве, позволяют переформатировать и реорганизовать пользовательский интерфейс в соответствии с шириной экрана. Это обеспечивает значительное преимущество в доступности, устраняя необходимость в горизонтальном панорамировании и раздражающих зигзагообразных движениях, которые в противном случае потребовались бы для чтения длинных строк текста.
Дополнительная информация : Исследования подтверждают, что для пользователей со слабым зрением переформатированный контент значительно более удобен для чтения и навигации, чем интерфейсы, требующие двухмерного панорамирования. Подробнее см. в статье «Сравнение контента с панорамированием и сканированием и переформатированного контента на мобильных устройствах» .
Масштабируйте либо все элементы, либо только текстовые элементы
В следующей таблице показан визуальный эффект каждой стратегии масштабирования.
| Стратегия | Масштабирование плотности | Масштабирование шрифта |
|---|---|---|
Поведение | Масштабирует всё пропорционально. Содержимое перестраивается, чтобы соответствовать контейнеру, поэтому пользователю не нужно панорамировать по горизонтали, чтобы увидеть всё содержимое. | Влияет только на текстовые элементы. Общий макет и нетекстовые компоненты остаются прежними по размеру. |
Что весы | Все визуальные элементы : текст, компоненты (кнопки, значки), изображения и пространство в макете (отступы, поля) | Только текст |
Демонстрация |
Рекомендации
Теперь, когда вы увидели визуальные различия, следующая таблица поможет вам взвесить компромиссы и выбрать наилучшую стратегию для вашего контента.
Тип пользовательского интерфейса | Рекомендуемая стратегия | Рассуждение |
Макеты, рассчитанные на интенсивное чтение Примеры: новостные статьи, приложения для обмена сообщениями. | Плотность или масштабирование шрифта | Масштабирование плотности предпочтительно для масштабирования всей области содержимого, включая встроенные изображения. Масштабирование шрифта — простая альтернатива, если нужно масштабировать только текст. |
Визуально структурированные макеты Примеры: магазины приложений, каналы социальных сетей. | Масштабирование плотности | Сохраняет визуальные связи между изображениями и текстом в каруселях или сетках. Перекомпоновка позволяет избежать горизонтального панорамирования, которое могло бы конфликтовать с вложенными прокручиваемыми элементами. |
Обнаружение жестов масштабирования в Jetpack Compose
Для поддержки масштабируемого пользователем контента необходимо сначала распознавать мультисенсорные жесты. В Jetpack Compose это можно сделать с помощью Modifier.transformable .
Модификатор transformable — это высокоуровневый API, предоставляющий информацию о дельте zoomChange с момента последнего события жеста. Это упрощает логику обновления состояния, позволяя использовать прямое накопление (например, scale *= zoomChange ), что делает его идеальным для стратегий адаптивного масштабирования, рассматриваемых в этом руководстве.
Примеры реализаций
В следующих примерах показано, как реализовать стратегии масштабирования плотности и масштабирования шрифта.
Масштабирование плотности
Этот подход масштабирует базовую density области пользовательского интерфейса. В результате все параметры макета, включая отступы, интервалы и размеры компонентов, масштабируются так, как будто изменились размер или разрешение экрана. Поскольку размер текста также зависит от плотности, он также масштабируется пропорционально. Эта стратегия эффективна, когда требуется равномерно увеличить все элементы в определённой области, сохраняя общий визуальный ритм и пропорции пользовательского интерфейса.
private class DensityScalingState( // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. private val minScale: Float = 0.75f, private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> scaleFactor.floatValue = (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) } val scaleFactor = mutableFloatStateOf(1f) fun scaledDensity(): Density { return Density( currentDensity.density * scaleFactor.floatValue, currentDensity.fontScale ) } }
Масштабирование шрифта
Эта стратегия более целенаправленная и изменяет только коэффициент fontScale . В результате увеличиваются или уменьшаются только текстовые элементы, в то время как все остальные компоненты макета, такие как контейнеры, отступы и значки, остаются фиксированного размера. Эта стратегия хорошо подходит для улучшения читаемости текста в приложениях с высокой интенсивностью чтения.
class FontScaleState( // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. private val minScale: Float = 0.75f, private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> scaleFactor.floatValue = (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) } val scaleFactor = mutableFloatStateOf(1f) fun scaledFont(): Density { return Density( currentDensity.density, currentDensity.fontScale * scaleFactor.floatValue ) } }
Общий демонстрационный пользовательский интерфейс
Это общая композиция DemoCard , используемая в обоих предыдущих примерах для демонстрации различного поведения масштабирования.
@Composable private fun DemoCard() { Card( modifier = Modifier .width(360.dp) .padding(16.dp), shape = RoundedCornerShape(12.dp) ) { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text("Demo Card", style = MaterialTheme.typography.headlineMedium) var isChecked by remember { mutableStateOf(true) } Row(verticalAlignment = Alignment.CenterVertically) { Text("Demo Switch", Modifier.weight(1f), style = MaterialTheme.typography.bodyLarge) Switch(checked = isChecked, onCheckedChange = { isChecked = it }) } Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Filled.Person, "Icon", Modifier.size(32.dp)) Spacer(Modifier.width(8.dp)) Text("Demo Icon", style = MaterialTheme.typography.bodyLarge) } Row( Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween ) { Box( Modifier .width(100.dp) .weight(1f) .height(80.dp) .background(Color.Blue) ) Box( Modifier .width(100.dp) .weight(1f) .height(80.dp) .background(Color.Red) ) } Text( "Demo Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit," + " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Justify ) } } }
Советы и соображения
Чтобы создать более удобный и доступный опыт, примите во внимание следующие рекомендации:
- Рассмотрите возможность предоставления управления весами без использования жестов : у некоторых пользователей могут возникнуть трудности с жестами. Чтобы поддержать таких пользователей, рассмотрите возможность предоставления альтернативного способа настройки или сброса весов, не требующего жестов.
- Создавайте для любого масштаба : протестируйте свой пользовательский интерфейс как с учётом масштабирования внутри приложения, так и с учётом общесистемных настроек шрифтов и отображения. Убедитесь, что макеты вашего приложения корректно адаптируются, не нарушая, не перекрывая и не скрывая контент. Узнайте больше о создании адаптивных макетов .