На телефонах ориентация экрана ограничена, но на больших экранах — нет.

Значок двухзвездочного рейтинга

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

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

Передовые методы

Лучшие приложения учитывают предпочтения пользователя, такие как ориентация экрана устройства.

Рекомендации по качеству адаптивных приложений предусматривают поддержку всех конфигураций устройств, включая портретную и альбомную ориентации, многооконный режим, а также сложенное и разложенное состояния складных устройств. Приложения должны оптимизировать макеты и пользовательские интерфейсы для различных конфигураций, а также сохранять и восстанавливать состояние при изменении конфигурации.

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

Ингредиенты

  • screenOrientation : Параметр в манифесте приложения, позволяющий указать, как ваше приложение реагирует на изменение ориентации устройства.
  • Activity#setRequestedOrientation() : Метод, с помощью которого можно изменить ориентацию приложения во время выполнения.
  • LocalConfiguration : Компонуемый локальный поставщик, предоставляющий доступ к текущей Configuration устройства, позволяющий считывать размеры экрана в DP.
  • LaunchedEffect : Создает API для побочных эффектов, который выполняет блок кода при изменении ключа (в данном случае, при изменении конфигурации).

Шаги

Включите в манифесте приложения возможность обработки изменений ориентации экрана по умолчанию. Затем, во время выполнения, используйте Jetpack Compose для динамического ограничения ориентации до портретной на компактных экранах (телефонах), разрешая при этом все ориентации на больших экранах.

1. Укажите параметры ориентации в манифесте приложения.

Вы можете либо не указывать элемент screenOrientation в манифесте приложения (в этом случае ориентация по умолчанию будет unspecified ), либо установить ориентацию экрана в fullUser . Если пользователь не заблокировал поворот экрана на основе данных датчиков, ваше приложение будет поддерживать все ориентации устройства.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

Разница между использованием unspecified и fullUser невелика, но важна. Если вы не указываете значение screenOrientation , система выбирает ориентацию самостоятельно, и политика, используемая системой для определения ориентации, может отличаться на разных устройствах. С другой стороны, указание fullUser более точно соответствует поведению, заданному пользователем для устройства: если пользователь заблокировал поворот экрана на основе датчиков, приложение следует предпочтениям пользователя; в противном случае система допускает любую из четырех возможных ориентаций экрана (портретная, альбомная, обратный портрет или обратный альбом). См. android:screenOrientation .

2. Динамическое ограничение ориентации в Compose.

В Jetpack Compose вы можете реактивно считывать текущие размеры экрана в DP из LocalConfiguration.current и использовать LaunchedEffect для обновления ориентации Activity при каждом изменении конфигурации.

Если ширина или высота экрана меньше 600dp (что соответствует точке перехода в компактный режим для телефонов), ограничьте ориентацию портретной. В противном случае разрешите системе поворачивать приложение в соответствии с предпочтениями пользователя ( unspecified или fullUser ).

Вот полная, компилируемая реализация:

val configuration = LocalConfiguration.current
val context = LocalActivity.current

LaunchedEffect(configuration) {
    val activity = context ?: return@LaunchedEffect
    // Determine if screen is compact (phone-sized) in either width or height
    val isCompact = configuration.screenWidthDp < 600 || configuration.screenHeightDp < 600
    activity.requestedOrientation = if (isCompact) {
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    } else {
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    }
}

Добавив логику внутрь блока LaunchedEffect(configuration) , вы сможете реактивно переопределять настройку ориентации всякий раз, когда изменяется конфигурация приложения, например, при изменении размера активности, перемещении между дисплеями или при складывании или раскладывании складного устройства.

Для получения дополнительной информации о том, когда происходят изменения конфигурации и когда они приводят к повторному выполнению действий, см. раздел «Обработка изменений конфигурации» .

Результаты

Теперь ваше приложение должно оставаться в портретной ориентации на небольших экранах независимо от поворота устройства. На больших экранах приложение должно поддерживать как альбомную, так и портретную ориентацию.

Дополнительные ресурсы

Для получения помощи по обновлению вашего приложения для постоянной поддержки всех конфигураций устройств см. следующие инструкции: