Ваше приложение отлично работает на телефонах с книжной ориентацией, поэтому вы ограничили его только портретной ориентацией. Но вы видите возможность делать больше на больших экранах в альбомной ориентации.
Как можно сделать и то, и другое — ограничить приложение портретной ориентацией на маленьких экранах, но включить альбомную ориентацию на больших?
Это руководство является временной мерой, пока вы не сможете улучшить свое приложение, чтобы обеспечить полную поддержку всех конфигураций устройств.
Управление ориентацией приложения
Чтобы включить альбомную ориентацию на больших экранах, настройте манифест приложения на обработку изменений ориентации по умолчанию. Во время выполнения определите размер окна приложения. Если окно приложения маленькое, ограничьте ориентацию приложения, переопределив настройку ориентации манифеста.
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:
![](https://developer.android.google.cn/static/images/quick-guides/collection-illustration.png?hl=ru)