ChromeOS поддерживает приложения Android в многооконном режиме. Система отображает приложения в оконных контейнерах, размер которых определяется форм-фактором устройства, как показано на рисунке 1.

Рисунок 1. Окно приложения на разных устройствах.
Важно разрабатывать макеты, которые работают с экранами разных размеров. Если вы будете следовать рекомендациям Android по поддержке разных размеров экрана , то ваше приложение также будет хорошо работать на ChromeOS.
На этой странице показано, как обеспечить корректный запуск окна вашего приложения, плавное изменение его размера и отображение всего его содержимого при изменении размера.
Начальный размер запуска
Приложения могут запросить свой первоначальный размер при запуске следующими способами:
Используйте заданный размер при запуске только в средах рабочего стола. Это поможет менеджеру окон правильно определить границы и ориентацию окна. Чтобы указать предпочтения при использовании в режиме рабочего стола, добавьте следующие метатеги внутри
<activity>:<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="[phone|tablet|maximize]" /> <meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="[portrait|landscape]" />Используйте статические границы запуска. Используйте
<layout>внутри записи манифеста вашей активности, чтобы указать «фиксированный» начальный размер, как в следующем примере:<layout android:defaultHeight="500dp" android:defaultWidth="600dp" android:gravity="top|end" android:minHeight="450dp" android:minWidth="300dp" />Используйте динамические границы запуска. Активность может создать и использовать
ActivityOptions.setLaunchBounds(Rect)при создании новой активности. Указав пустой прямоугольник, вы сможете развернуть приложение на весь экран.
Изменение размера окон
В ChromeOS пользователи могут изменять размер окна приложения обычным способом: перетаскивая нижний правый угол, как показано на рисунке 2.

Рисунок 2. Окно приложения с изменяемым размером.
При использовании класса View существует два варианта обработки изменения размера окна:
- Динамически реагируйте на изменения конфигурации, вызывая
onConfigurationChanged(..). Например, вы можете добавитьandroid:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"в манифест активности. Для получения дополнительной информации об обработке изменений конфигурации см. раздел «Обработка изменений конфигурации» . - Позвольте системе перезапустить активность. В этом случае реализуйте
onSaveInstanceStateи используйте компонент архитектуры ViewModel для восстановления предыдущего сохраненного состояния.
При использовании Jetpack Compose поведение изменения размера зависит от конфигурации вашей активности. Если изменения обрабатываются динамически, при изменении размера окна запускается перекомпозиция. Если активность перезапускается системой, после перезапуска происходит первоначальная компоновка. В любом случае важно создавать макеты Compose, которые адаптируются к изменяющимся размерам окон. Не следует предполагать фиксированные размеры.
Размеры окна
Настройте ваши приложения так, чтобы они каждый раз при запуске считывали размеры своих окон и располагали содержимое в соответствии с текущей конфигурацией.
Чтобы определить текущую конфигурацию, вызовите getResources().getConfiguration() для текущей активности. Не используйте конфигурацию фоновой активности или системного ресурса. Фоновая активность не имеет размера, а системная конфигурация может содержать несколько окон с конфликтующими размерами и ориентациями, поэтому извлечь полезные данные невозможно.
Обратите внимание, что размер окна и размер экрана — это не одно и то же. Чтобы получить размер окна в DP, используйте Activity.getResources().getConfiguration().screenWidth и Activity.getResources().getConfiguration().screenHeight . Вам, вероятно, никогда не понадобится использовать размер экрана.
Ограничения содержимого
Границы содержимого окна могут изменяться после изменения его размера. Например, область внутри окна, используемая приложением, может измениться, если окно станет слишком большим, чтобы поместиться на экране. Следуйте этим рекомендациям:
- Приложения, использующие встроенную в Android функцию компоновки, автоматически размещаются в доступном пространстве.
Нативные приложения должны считывать доступную область и отслеживать изменения размера, чтобы избежать недоступности элементов пользовательского интерфейса. Вызовите следующие методы, чтобы определить начальный доступный размер этой поверхности:
-
NativeActivity.mLastContent[X/Y/Width/Height]() -
findViewById(android.R.id.content).get[Width/Height]()
Непрерывный мониторинг можно осуществлять с помощью наблюдателя:
-
NativeActivity.onContentRectChangedNative() -
NativeActivity.onGlobalLayout() - Добавьте слушатель событий к представлению:
view.addOnLayoutChangeListener(findViewById(android.R.id.content))
Если приложение предварительно масштабирует изображения, делайте это каждый раз при изменении разрешения.
-
Свободное изменение размера
ChromeOS позволяет свободно изменять размер любого окна: пользователь может изменять ширину, высоту и положение окна на экране. Многие приложения для Android разработаны без учета возможности свободного изменения размера. Рассмотрим следующие проблемы:
- Положение на экране может измениться. Всегда используйте систему для выполнения преобразований координат из окна на экран и из экрана в окно.
- Если вы используете систему отображения Android, расположение окон автоматически изменяется при изменении их размера.
- Если вы не используете систему отображения и не захватываете поверхность целиком, ваше приложение должно самостоятельно обрабатывать изменения размера.
- Для нативных приложений используйте элементы
mLastContentили представление контента, чтобы определить начальный размер. - Когда приложение запущено, отслеживайте события
onContentRectChangedNativeилиonGlobalLayout, чтобы реагировать на изменения размера. - При изменении размера приложения измените масштаб или перезагрузите макеты и графику, а также обновите области ввода.
Полноэкранный режим
Полноэкранный режим работает так же, как и в стандартном Android. Если окно не занимает весь экран, запросы на полноэкранный режим (скрытие всех элементов системного интерфейса) игнорируются. При разворачивании приложения на весь экран выполняются обычные методы, макеты и функции полноэкранного режима. Это скрывает элементы системного интерфейса (панель управления окном и панель инструментов).
Ориентация экрана
Наиболее распространенная ориентация для Android-приложений — портретная, поскольку именно так держат большинство телефонов. Хотя портретная ориентация хороша для телефонов, она совершенно не подходит для ноутбуков и планшетов, где предпочтительнее альбомная. Для достижения наилучших результатов для вашего приложения рекомендуется поддерживать обе ориентации.
Некоторые приложения для Android предполагают, что при удержании устройства в портретном режиме значение поворота равно Surface.ROTATION_0 . Это может быть верно для большинства устройств Android. Однако, когда приложение находится в определенном режиме ARC , значение поворота для портретной ориентации может быть не равно Surface.ROTATION_0 .
Для получения точного значения поворота при считывании данных с акселерометра или аналогичных датчиков используйте метод Display.getRotation() и соответствующим образом поменяйте местами оси.
Активность и ориентация корней
Окно Chromebook состоит из стека окон активности. Каждое окно в стеке имеет одинаковый размер и ориентацию.
Внезапные изменения ориентации и размера в настольной среде вызывают путаницу. Менеджер окон Chromebook избегает этого, используя подход, аналогичный режиму «бок о бок» в Android: активность внизу стека управляет атрибутами всех активностей над ней. Это может привести к неожиданным ситуациям, когда только что запущенная активность в портретном режиме без возможности изменения размера становится в альбомном режиме с возможностью изменения размера.
Здесь вступает в действие режим устройства: в режиме планшета ориентация не блокируется, и каждое окно сохраняет свою собственную ориентацию, как это обычно происходит на Android.
Руководство по ознакомлению
Для прохождения инструктажа по обращению с пациентами следуйте этим рекомендациям:
- Если поддерживается только одна ориентация экрана, добавьте эту информацию в манифест, чтобы оконный менеджер знал о ней до запуска приложения. При указании ориентации, по возможности, также указывайте ориентацию датчиков. Chromebook часто являются трансформерами, и приложение, отображаемое вверх ногами, ухудшает пользовательский опыт.
- Старайтесь использовать только одну выбранную ориентацию. Избегайте указания одной ориентации в манифесте и последующей программной установки другой.
- Будьте осторожны при изменении ориентации окна в зависимости от его размера. Пользователь может застрять в маленьком окне портретного формата и не иметь возможности вернуться к большему окну альбомной ориентации.
- В Chrome есть элементы управления окнами, позволяющие переключаться между всеми доступными макетами. Выбрав правильный вариант ориентации, вы можете гарантировать, что пользователь увидит правильный макет после запуска приложения. Если приложение доступно в портретном и альбомном режимах, по возможности установите его по умолчанию в альбомный режим. После установки этот параметр будет запоминаться для каждого приложения отдельно.
- Старайтесь избегать ненужных изменений ориентации. Например, если ориентация активности портретная, но приложение вызывает
setRequestedOrientation(LANDSCAPE)во время выполнения, это приводит к ненужному изменению размера окна, что раздражает пользователя и может привести к перезапуску приложения, если оно не сможет это обработать. Лучше установить ориентацию один раз, например, в манифесте, и изменять её только при необходимости.
Другие соображения
Вот еще несколько моментов, которые следует учитывать при работе с приложениями Android в ChromeOS:
- Не вызывайте
finish()в методеonDestroyвашего Activity. Это приведет к закрытию приложения при изменении размера экрана, а не к его перезапуску. - Не используйте несовместимые типы окон, такие как
TYPE_KEYGUARDиTYPE_APPLICATION_MEDIA. - Для ускорения перезапуска активности используйте кэширование объектов, которые были выделены ранее.
- Если вы не хотите, чтобы пользователь изменял размер вашего приложения, укажите
android:resizeableActivity=falseв файле манифеста. - Протестируйте свое приложение, чтобы убедиться, что оно корректно обрабатывает изменения размера окна.