Ваше приложение отлично работает на телефонах в портретной ориентации, поэтому вы ограничили его только портретной ориентацией. Но вы видите возможность расширить возможности на больших экранах в альбомной ориентации.
Как можно совместить два варианта — ограничить работу приложения в портретной ориентации на маленьких экранах и включить альбомную ориентацию на больших?
Это руководство является временной мерой, пока вы не улучшите свое приложение, обеспечив полную поддержку всех конфигураций устройств.
Результаты
Ваше приложение сохраняет портретную ориентацию на маленьких экранах независимо от поворота устройства. На больших экранах приложение поддерживает альбомную и портретную ориентацию.
Управление ориентацией приложения
Чтобы включить альбомную ориентацию на больших экранах, настройте манифест приложения на обработку изменений ориентации по умолчанию. Определите размер окна приложения во время выполнения. Если окно приложения небольшое, ограничьте ориентацию приложения, переопределив настройку ориентации в манифесте.
1. Укажите настройки ориентации в манифесте приложения.
Вы можете либо не объявлять элемент screenOrientation
в манифесте приложения (в этом случае ориентация по умолчанию будет unspecified
), либо установить ориентацию экрана fullUser
. Если пользователь не заблокировал поворот экрана с помощью датчиков, ваше приложение будет поддерживать все ориентации устройства.
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
Разница между unspecified
и fullUser
невелика, но важна. Если значение screenOrientation
не указано, система выбирает ориентацию, и политика, используемая системой для определения ориентации, может различаться на разных устройствах. С другой стороны, указание fullUser
более точно соответствует поведению, заданному пользователем для устройства: если пользователь заблокировал поворот экрана по датчику, приложение следует его настройкам; в противном случае система допускает любую из четырёх возможных ориентаций экрана (книжную, альбомную, перевёрнутую книжную или перевёрнутую альбомную). См. screenOrientation
.
2. Определите размер экрана
Настроив манифест на поддержку всех разрешенных пользователем ориентаций, вы можете программно указать ориентацию приложения на основе размера экрана.
Добавьте библиотеки Jetpack WindowManager в файл build.gradle
или build.gradle.kts
модуля:
Котлин
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Круто
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
Используйте метод Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics()
для получения размера экрана устройства в виде объекта WindowMetrics
. Метрики окна можно сравнить с классами размеров окна, чтобы определить, когда следует ограничить ориентацию.
Классы размеров Windows обеспечивают контрольные точки между маленькими и большими экранами.
Используйте контрольные точки WindowWidthSizeClass#COMPACT
и WindowHeightSizeClass#COMPACT
для определения размера экрана:
Котлин
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Ява
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- Примечание:
- Примеры реализованы как методы действия; поэтому действие разыменовывается как
this
в аргументеcomputeMaximumWindowMetrics()
. - Метод
computeMaximumWindowMetrics()
используется вместоcomputeCurrentWindowMetrics()
, поскольку приложение может запускаться в многооконном режиме, который игнорирует настройки ориентации экрана. Определение размера окна приложения и переопределение настроек ориентации не имеет смысла, если только окно приложения не занимает весь экран устройства.
Инструкции по объявлению зависимостей для обеспечения доступности метода computeMaximumWindowMetrics()
в вашем приложении см. в разделе WindowManager.
3. Переопределить настройки манифеста приложения
Когда вы определили, что устройство имеет компактный размер экрана, вы можете вызвать Activity#setRequestedOrientation()
чтобы переопределить настройку screenOrientation
манифеста:
Котлин
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Ява
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
Добавив логику в методы onCreate()
и View.onConfigurationChanged()
, вы сможете получить максимальные метрики окна и переопределить настройку ориентации при изменении размера или перемещении активности между дисплеями, например, после поворота устройства или при складывании/раскладывании складного устройства. Подробнее о том, когда происходят изменения конфигурации и когда они приводят к повторному запуску активности, см. в разделе Обработка изменений конфигурации .
Ключевые моменты
-
screenOrientation
: настройка манифеста приложения, позволяющая указать, как приложение реагирует на изменения ориентации устройства. - Jetpack WindowManager : набор библиотек, позволяющих определять размер и соотношение сторон окна приложения; обратно совместим с API уровня 14.
-
Activity#setRequestedOrientation()
: Метод, с помощью которого можно изменить ориентацию приложения во время выполнения.
Коллекции, содержащие это руководство
Это руководство является частью тщательно подобранной коллекции кратких руководств, охватывающих более широкие цели разработки Android:

Оптимизировать для больших экранов
Есть вопросы или отзывы
Ваше приложение отлично работает на телефонах в портретной ориентации, поэтому вы ограничили его только портретной ориентацией. Но вы видите возможность расширить возможности на больших экранах в альбомной ориентации.
Как можно совместить два варианта — ограничить работу приложения в портретной ориентации на маленьких экранах и включить альбомную ориентацию на больших?
Это руководство является временной мерой, пока вы не улучшите свое приложение, обеспечив полную поддержку всех конфигураций устройств.
Результаты
Ваше приложение сохраняет портретную ориентацию на маленьких экранах независимо от поворота устройства. На больших экранах приложение поддерживает альбомную и портретную ориентацию.
Управление ориентацией приложения
Чтобы включить альбомную ориентацию на больших экранах, настройте манифест приложения на обработку изменений ориентации по умолчанию. Определите размер окна приложения во время выполнения. Если окно приложения небольшое, ограничьте ориентацию приложения, переопределив настройку ориентации в манифесте.
1. Укажите настройки ориентации в манифесте приложения.
Вы можете либо не объявлять элемент screenOrientation
в манифесте приложения (в этом случае ориентация по умолчанию будет unspecified
), либо установить ориентацию экрана fullUser
. Если пользователь не заблокировал поворот экрана с помощью датчиков, ваше приложение будет поддерживать все ориентации устройства.
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
Разница между unspecified
и fullUser
невелика, но важна. Если значение screenOrientation
не указано, система выбирает ориентацию, и политика, используемая системой для определения ориентации, может различаться на разных устройствах. С другой стороны, указание fullUser
более точно соответствует поведению, заданному пользователем для устройства: если пользователь заблокировал поворот экрана по датчику, приложение следует его настройкам; в противном случае система допускает любую из четырёх возможных ориентаций экрана (книжную, альбомную, перевёрнутую книжную или перевёрнутую альбомную). См. screenOrientation
.
2. Определите размер экрана
Настроив манифест на поддержку всех разрешенных пользователем ориентаций, вы можете программно указать ориентацию приложения на основе размера экрана.
Добавьте библиотеки Jetpack WindowManager в файл build.gradle
или build.gradle.kts
модуля:
Котлин
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Круто
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
Используйте метод Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics()
для получения размера экрана устройства в виде объекта WindowMetrics
. Метрики окна можно сравнить с классами размеров окна, чтобы определить, когда следует ограничить ориентацию.
Классы размеров Windows обеспечивают контрольные точки между маленькими и большими экранами.
Используйте контрольные точки WindowWidthSizeClass#COMPACT
и WindowHeightSizeClass#COMPACT
для определения размера экрана:
Котлин
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Ява
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- Примечание:
- Примеры реализованы как методы действия; поэтому действие разыменовывается как
this
в аргументеcomputeMaximumWindowMetrics()
. - Метод
computeMaximumWindowMetrics()
используется вместоcomputeCurrentWindowMetrics()
, поскольку приложение может запускаться в многооконном режиме, который игнорирует настройки ориентации экрана. Определение размера окна приложения и переопределение настроек ориентации не имеет смысла, если только окно приложения не занимает весь экран устройства.
Инструкции по объявлению зависимостей для обеспечения доступности метода computeMaximumWindowMetrics()
в вашем приложении см. в разделе WindowManager.
3. Переопределить настройки манифеста приложения
Когда вы определили, что устройство имеет компактный размер экрана, вы можете вызвать Activity#setRequestedOrientation()
чтобы переопределить настройку screenOrientation
манифеста:
Котлин
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Ява
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
Добавив логику в методы onCreate()
и View.onConfigurationChanged()
, вы сможете получить максимальные метрики окна и переопределить настройку ориентации при изменении размера или перемещении активности между дисплеями, например, после поворота устройства или при складывании/раскладывании складного устройства. Подробнее о том, когда происходят изменения конфигурации и когда они приводят к повторному запуску активности, см. в разделе Обработка изменений конфигурации .
Ключевые моменты
-
screenOrientation
: настройка манифеста приложения, позволяющая указать, как приложение реагирует на изменения ориентации устройства. - Jetpack WindowManager : набор библиотек, позволяющих определять размер и соотношение сторон окна приложения; обратно совместим с API уровня 14.
-
Activity#setRequestedOrientation()
: Метод, с помощью которого можно изменить ориентацию приложения во время выполнения.
Коллекции, содержащие это руководство
Это руководство является частью тщательно подобранной коллекции кратких руководств, охватывающих более широкие цели разработки Android:
