|
| 1 | +--- |
| 2 | +title: Android 15 UI Changes |
| 3 | +description: User experience and system UI changes in Android 15 (v35) |
| 4 | +image: images/android.png |
| 5 | +authors: [ marchbold ] |
| 6 | +tags: [ android, tips ] |
| 7 | +--- |
| 8 | + |
| 9 | +Android 15 (API v35) includes some changes that are intended to create a more consistent, intuitive user experience. |
| 10 | + |
| 11 | +:::note |
| 12 | +You can read the official release of this information here: https://developer.android.com/about/versions/15/behavior-changes-15 |
| 13 | +::: |
| 14 | + |
| 15 | +## Window inset changes |
| 16 | + |
| 17 | +There are two changes related to window insets in Android 15: edge-to-edge is enforced by default, and there are also configuration changes, such as the default configuration of system bars. |
| 18 | + |
| 19 | +### Edge-to-edge enforcement |
| 20 | + |
| 21 | +Apps are edge-to-edge by default on devices running Android 15 if the app is targeting Android 15 (API level 35). |
| 22 | + |
| 23 | + |
| 24 | +An app that targets Android 14 and is not edge-to-edge on an Android 15 device. The application is contained within the window insets. |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +After updating your target sdk to 35 you will find that your application is now expected to handle the window insets and is rendered edge-to-edge. However, many elements are now hidden by the status bar, 3-button navigation bar, or display cutout due to the Android 15 edge-to-edge enforcements. |
| 29 | + |
| 30 | + |
| 31 | + |
| 32 | +You will need to update your application to correctly handle rendering within the window insets and render within these bounds so UI elements are not hidden. |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +### Handling window insets |
| 38 | + |
| 39 | +To get the safe area to render you can use the [Application](https://airnativeextensions.com/extension/com.distriqt.Application) extension to retrieve the display cutout information: |
| 40 | + |
| 41 | +```actionscript |
| 42 | +var displayCutout:DisplayCutout = Application.service.display.getDisplayCutout(); |
| 43 | +``` |
| 44 | + |
| 45 | +This object contains 4 properties: `safeInsetBottom`, `safeInsetTop`, `safeInsetLeft`, `safeInsetRight`, each indicating the number of pixels from the edge of the screen that system bars or cutouts may affect. |
| 46 | + |
| 47 | +There is also an `boundingRects` property containing detailed areas for any cutouts that may affect rendering. |
| 48 | + |
| 49 | + |
| 50 | +You can use this to apply bounds to your root content "safe area", eg using a starling `_safeArea` object for rendering UI elements you can use something like the following : |
| 51 | + |
| 52 | +```actionscript |
| 53 | +if (Application.isSupported) |
| 54 | +{ |
| 55 | + var cutout:DisplayCutout = Application.service.display.getDisplayCutout(); |
| 56 | + var topInset:Number = cutout.safeInsetTop / _scale; |
| 57 | + var bottomInset:Number = cutout.safeInsetBottom / _scale; |
| 58 | + var leftInset:Number = cutout.safeInsetLeft / _scale; |
| 59 | + var rightInset:Number = cutout.safeInsetRight / _scale; |
| 60 | +
|
| 61 | + _safeArea.setTo(leftInset, topInset, |
| 62 | + _stageWidth - leftInset - rightInset, |
| 63 | + _stageHeight - topInset - bottomInset); |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +:::note |
| 68 | +If you use immersive mode or change display modes at any time in your application you should ensure to reapply these corrections afterwards. |
| 69 | +::: |
| 70 | + |
| 71 | + |
| 72 | +### Cutouts |
| 73 | + |
| 74 | +If your app targets SDK 35 and is running on an Android 15 device, `LayoutMode.CUTOUT_ALWAYS` is the default behavior. This means that if you were previously relying on setting the LayoutMode eg via calling |
| 75 | + |
| 76 | +```actionscript |
| 77 | +Application.service.display.setDisplayMode( |
| 78 | + DisplayMode.FULLSCREEN, |
| 79 | + LayoutMode.CUTOUT_NEVER ); |
| 80 | +``` |
| 81 | + |
| 82 | +this will be interpretted as "always" and your content will be drawn into cutout regions. |
| 83 | + |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | +### Opt-out |
| 88 | + |
| 89 | +As a temporary workaround you can opt-out of this edge-to-edge enforcement in v35. |
| 90 | + |
| 91 | +:::caution |
| 92 | +This option to opt-out will be removed once you update to target v36, so this workaround should only be treated as temporary. |
| 93 | +::: |
| 94 | + |
| 95 | +Firstly, create a custom resources folder in your application and package it according to the guide [here](https://airsdk.dev/docs/tutorials/platform/android/custom-resources). |
| 96 | + |
| 97 | +Under your resources folder create a `values-v35` folder and add a file `styles.xml` into this folder with the following content: |
| 98 | + |
| 99 | +```xml title="styles.xml" |
| 100 | +<?xml version="1.0" encoding="utf-8"?> |
| 101 | +<resources> |
| 102 | + |
| 103 | + <style name="Theme.NoShadow" parent="android:style/Theme.NoTitleBar"> |
| 104 | + <item name="android:windowContentOverlay">@null</item> |
| 105 | + <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item> |
| 106 | + </style> |
| 107 | + |
| 108 | +</resources> |
| 109 | +``` |
| 110 | + |
| 111 | +The `android:windowOptOutEdgeToEdgeEnforcement` option is the critical one that will disable this edge-to-edge enforcement for Android 35. |
| 112 | + |
0 commit comments