ChromeOS runs Android apps in individual windows. These windows can be resized or maximized, and will be resized accordingly when a tablet or convertible device is rotated.
Users can resize app windows by clicking and dragging the window borders. This brings additional considerations for Android apps that may have been designed for phones.
In the Android lifecycle, when an app is resized or its orientation changes, in addition to other runtime configuration changes, the Activity’s UI is torn down and rebuilt. Specifically, onPause(), onStop(), and onDestroy() will be called to clean up the old UI, followed by onCreate(), onStart(), and onResume()to rebuild it.
At first glance, it may seem strange to tear down and rebuild the UI on every configuration change, however it is part of what makes it possible for Android apps to run well on so many devices and in any shape of window, while looking great with quality graphics and an optimized layout.
Older apps developed for mobile phones may not be expecting to receive these types of configuration changes very frequently. In particular, some apps do intensive processing or disk/network fetches in their
onCreate method which can cause performance issues or crashes on window resizing. In addition, state can be lost during these lifecycle events which can cause inconvenience or data loss for users.
Mobile apps that rely on forcing a portrait or landscape layout and disallowing rotation in order to avoid these lifecycle events will not behave correctly when they are resized in a windowed environment.
There are two options for handling window resizing. Most apps should implement the first one, and it is good practice across all Android devices, even if you are not targeting ChromeOS.
- All UI state should be maintained in a ViewModel combined with the SavedState module or an onSavedInstanceState implementation. Other data should be handled with Lifecycle aware components. See Jetpack’s guide to app architecture for a list of components that can make this robust and straightforward to implement.
This will ensure an app’s UI is decoupled from user data and expensive data operations. Resizing can then happen quickly and fluidly. Other mobile devices, tablets, and foldables will also benefit from this implementation by handling configuration changes well. This is not the only way to achieve this behavior, but it is the recommended way.
- You can also handle configuration changes yourself. This requires careful attention and can lead to poor behavior if you receive unexpected configuration changes - for example if screen density changes when a user plugs in an external monitor. However, some apps, games, and games engines may wish to handle configuration changes caused by window resizing manually. To do this, add the following line to the
<Activity>tag in your
and then override the
onConfigurationChanged method in your main activity. See handling configuration changes yourself for more information and other possible configuration change events.
To make you app or activity non-resizable add the
In windowed environments, Activities can be resized. When possible, apps should implement fluid layouts using ConstraintLayout. Apps also should consider adding alternative screen layouts based on window dimensions to provide the best use of space and an optimal UI. Further advice for thinking through your layout architecture is found on the Design Recommendations page.
If your app needs to manually calculate layout dimensions at runtime, get the current window dimensions in dp (density independent pixels) using getConfiguration or in raw pixels using displayMetrics as demonstrated below. Be sure to check for new window dimensions in every onCreate call or on every configuration change if you are handling configurations changes yourself.
Apps designed for large screens should support both large landscape and portrait screens. Apps that are forced to run in a single orientation will provide a poor experience for users.
If your app is designed for portrait devices and providing an optimal landscape layout is not possible, consider adding a graphically pleasing, contextual, landscape background to the app to prevent black bars appearing on the sides or having your app placed in a small window. See Orientation and Configuration Changes on the Games on ChromeOS page for more information.
Apps can specify their initial launch size in the following ways:
Use a specific launch size only in windowed environments: This helps the ChromeOS window manager give the desired launch bounds and orientation to an app and will not affect behaviour on mobile devices. To indicate launch preferences, add the following ChromeOS specific meta tags inside the Activity element of the
Use static launch bounds: Include a
AndroidManifest.xmlfile to specify an initial window size:
Use dynamic launch bounds: An app can use setLaunchBounds(Rect) when creating a new Activity. If an empty rectangle is specified, the Activity will be started in a maximized state.