Insets dealing with ideas for Android 15’s edge-to-edge enforcement | by Ash Nohe | Android Builders | Sep, 2024

0
20
Insets dealing with ideas for Android 15’s edge-to-edge enforcement | by Ash Nohe | Android Builders | Sep, 2024


We will use the window inset listener so that each one record objects, together with the final record merchandise, are padded above the navigation bar.

Determine 12. App has dealt with insets, however feels much less immersive as a result of content material doesn’t scroll behind system bars.
// Determine 12
ViewCompat.setOnApplyWindowInsetsListener(
findViewById(R.id.recycler_view)
) { v, insets ->
val innerPadding = insets.getInsets(
// Discover we're utilizing systemBars, not statusBar
WindowInsetsCompat.Kind.systemBars()
// Discover we're additionally accounting for the show cutouts
or WindowInsetsCompat.Kind.displayCutout()
// If utilizing EditText, additionally add
// "or WindowInsetsCompat.Kind.ime()"
// to keep up focus when opening the IME
)
v.setPadding(
innerPadding.left,
innerPadding.prime,
innerPadding.proper,
innerPadding.backside)
insets
}

Nevertheless, now the app seems much less immersive. To get the end result we would like, add clipToPadding=false to make sure the final record merchandise sits above the navigation bar and the record is seen whereas scrolling behind the navigation bar (and standing bar).

Determine 13. App shows edge-to-edge and the final record merchandise is absolutely seen. That is the end result we would like.

...
android:clipToPadding="false" />

5. Don’t neglect IMEs

Set android:windowSoftInputMode=”adjustResize” in your Exercise’s AndroidManifest.xml entry to make room for the IME (or smooth keyboard) on display screen.

Dealing with IMEs insets in Compose

Account for the IME utilizing Modifier.imePadding(). For instance, this may also help preserve deal with a TextField in a LazyColumn when the IME opens. See the Inset consumption part for a code instance and clarification.

Dealing with IMEs insets in Views

Earlier than concentrating on SDK 35, utilizing android:windowSoftInputMode=”adjustResize” was all you wanted to keep up deal with — for instance — an EditText in a RecyclerView when opening an IME. With “adjustResize”, the framework handled the IME because the system window, and the window’s root views had been padded so content material avoids the system window.

After concentrating on SDK 35, you have to additionally account for the IME utilizing ViewCompat.setOnApplyWindowInsetsListener and WindowInsetsCompat.Kind.ime() as a result of the framework will not pad the window’s root views. See Determine 12’s code instance.

6. For backward compatibility, use enableEdgeToEdge as an alternative of setDecorFitsSystemWindows

After your app has dealt with insets, make your app edge-to-edge on earlier Android variations. For this, use enableEdgeToEdge as an alternative of setDecorFitsSystemWindows. The enableEdgeToEdge methodology encapsulates the about 100 traces of code it’s good to be really backward suitable.

7. Background defend system bars solely when needed

In lots of circumstances, hold the brand new Android 15 defaults. The standing bar and gesture navigation bar ought to be clear, and three button navigation translucent after concentrating on SDK 35 (see Determine 1).

Nevertheless, there are some circumstances the place you want to protect the background coloration of the system bars, however the APIs to set the standing and navigation bar colours are deprecated. We’re planning to launch an AndroidX library to assist this use case. Within the meantime, in case your app should provide customized background safety to 3-button navigation or the standing bar, you’ll be able to place a composable or view behind the system bar utilizing WindowInsets.Kind#tappableElement() to get the 3-button navigation bar peak or WindowInsets.Kind#statusBars.

For instance, to indicate the colour of the aspect behind the 3-button navigation in Compose, set the window.isNavigationBarContrastEnforced property to false. Setting this property to false makes 3-button navigation absolutely clear (be aware: this property does not have an effect on gesture navigation).

Then, use WindowInsets.tappableElement to align UI behind insets for tappable system UI. If non-0, the person is utilizing tappable bars, like three button navigation. On this case, draw an opaque view or field behind the tappable bars.

class MainActivity : ComponentActivity() {
override enjoyable onCreate(savedInstanceState: Bundle?) {
tremendous.onCreate(savedInstanceState)
setContent {
window.isNavigationBarContrastEnforced = false
MyTheme {
Floor(...) {
MyContent(...)
ProtectNavigationBar()
}
}
}
}
}

// Use provided that required.
@Composable
enjoyable ProtectNavigationBar(modifier: Modifier = Modifier) {
val density = LocalDensity.present
val tappableElement = WindowInsets.tappableElement
val bottomPixels = tappableElement.getBottom(density)
val usingTappableBars = bear in mind(bottomPixels) {
bottomPixels != 0
}
val barHeight = bear in mind(bottomPixels) {
tappableElement.asPaddingValues(density).calculateBottomPadding()
}

Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Association.Backside
) {
if (usingTappableBars) {
Field(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxWidth()
.peak(barHeight)
)
}
}
}

The next ideas apply just for apps that use Jetpack Compose. See further Compose-related ideas on this video: Edge-to-edge and insets | Compose Ideas.

8. Use Scaffold’s PaddingValues

For Compose, use Scaffold as an alternative of Floor to arrange your app’s UI with TopAppBar, BottomAppBar, NavigationBar, and NavigationRail. Use Scaffold’s PaddingValues parameter to inset your vital UI. Most often, that’s all it’s good to do.

Nevertheless, there are circumstances the place making use of Scaffold’s PaddingValues will trigger surprising outcomes. Scaffold’s PaddingValues consists of insets for the highest, backside, begin and finish edges of the display screen. Chances are you’ll want values for less than sure edges. One strategy is to make a replica of the parameter and manually modify prime, backside, begin and finish insets in order to not apply an excessive amount of padding.

Determine 14. Left: The enter discipline on the backside is obscured by the system’s navigation bar after concentrating on SDK 35. Center: Scaffold’s PaddingValues utilized to the enter discipline. The system makes use of the dimensions of the standing bar and the highest app bar to calculate the highest padding worth, which creates extra padding above the enter discipline. Proper: Scaffold’s PaddingValues utilized however with prime padding manually eliminated.

Right here’s the inaccurate code, inflicting the surplus padding seen within the center picture of Determine 14.

// Causes extra padding, seen within the center picture of Determine 14.
Scaffold { innerPadding -> // innerPadding is Scaffold's PaddingValues
InputBar(
...
contentPadding = innerPadding
) {...}
}

Right here’s the corrected code that generates correct padding, as seen within the right-side picture of Determine 14.

// Operate to make a replica of PaddingValues, utilizing present defaults until an
// various worth is specified
​​personal enjoyable PaddingValues.copy(
layoutDirection: LayoutDirection,
begin: Dp? = null,
prime: Dp? = null,
finish: Dp? = null,
backside: Dp? = null,
) = PaddingValues(
begin = begin ?: calculateStartPadding(layoutDirection),
prime = prime ?: calculateTopPadding(),
finish = finish ?: calculateEndPadding(layoutDirection),
backside = backside ?: calculateBottomPadding(),
)

// Produces appropriate padding, seen within the right-side picture of Determine 14.
Scaffold { innerPadding -> // innerPadding is Scaffold's PaddingValues
val layoutDirection = LocalLayoutDirection.present
InputBar(
...
contentPadding = innerPadding.copy(layoutDirection, prime = 0.dp)
) {...}
}

9. Use excessive degree WindowInsets APIs

Much like Scaffold’s PaddingValues, you can even use the high-level WindowInset APIs to simply and safely draw vital UI parts. These are:

See Inset fundamentals to be taught extra.

The next apply just for Views-based apps.

10. Favor ViewCompat.setOnApplyWindowInsetsListener over fitsSystemWindows=true

You may use fitsSystemWindows=true to inset your app’s content material. It’s a straightforward 1-line code change. Nevertheless, don’t use fitsSystemWindows on a View that incorporates your total format (together with the background). It will make your app look not edge-to-edge as a result of fitsSystemWindows handles insets on all edges.

Determine 15. Edge-to-edge enforced. Left: fitsSystemWindows=false (the default). Proper: fitsSystemWindows=true. This isn’t the end result we would like as a result of the app doesn’t look edge-to-edge.
Determine 16. Edge-to-edge enforced, fitsSystemWindows=true. The hole on the left edge is because of a show cutout, which isn’t seen right here. This isn’t the end result we would like as a result of the app doesn’t look edge-to-edge.

fitsSystemWindows can create an edge-to-edge expertise if utilizing CoordinatorLayouts or AppBarLayouts.Add fitsSystemWindows to the CoordinatorLayout and the AppBarLayout, and the AppBarLayout attracts edge-to-edge, which is what we would like.

Determine 17. Edge-to-edge enforced. Left: AppBarLayout doesn’t routinely deal with insets. Proper: Add fitsSystemWindows to AppBarLayout and CoordinatorLayout to attract edge-to-edge.

android:fitsSystemWindows="true"
...>
android:fitsSystemWindows="true"
...>
android:textual content="App Bar Structure"
.../>

On this case, AppBarLayout used fitsSystemWindows to attract beneath the standing bar slightly than avoiding it, which is the other of what we would anticipate. Moreover, AppBarLayout with fitsSystemWindows=true solely applies padding for the highest and never the underside, begin, or finish edges.

The CoordinatorLayout and AppBarLayout objects have the next habits when overriding fitsSystemWindows:

  • CoordinatorLayout: backgrounds of kid views draw beneath the system bars if these views additionally set fitsSystemWindows=true. Padding is routinely utilized to the content material of these Views (e.g. textual content, icons, photos) to account for system bars and show cutouts.
  • AppBarLayout: attracts beneath the system bars if fitsSystemWindows=true and routinely applies prime padding to content material.

Most often, deal with insets with ViewCompat.setOnApplyWindowInsetsListener as a result of it lets you outline which edges ought to deal with insets and has constant habits. See ideas #4 and #11 for a code instance.

11. Apply insets primarily based on app bar peak through the format section

In the event you discover that your app’s content material is hiding beneath an app bar, you may want to use insets after the app bar is laid out, taking the app bar peak under consideration.

For instance, when you’ve got scrolling content material beneath an AppBarLayout in a FrameLayout, you possibly can use code like this to make sure the scrolling content material seems after the AppBarLayout. Discover padding is utilized inside doOnLayout.

val myScrollView = findViewById(R.id.my_scroll_view)
val myAppBar = findViewById(R.id.my_app_bar_layout)

ViewCompat.setOnApplyWindowInsetsListener(myScrollView) { scrollView, windowInsets ->
val insets = windowInsets.getInsets(
WindowInsetsCompat.Kind.systemBars() or WindowInsetsCompat.Kind.displayCutout()
)
myAppBar.doOnLayout { appBar ->
scrollView.updatePadding(
left = insets.left,
proper = insets.proper,
prime = appBar.peak,
backside = insets.backside
)
}
WindowInsetsCompat.CONSUMED
}

Likewise, when you’ve got scrolling content material that ought to sit above a BottomNavigationView, you’ll wish to account for the BottomNavigationView’s peak as soon as it’s laid out.

It would take vital work to correctly assist an edge-to-edge expertise. Earlier than you goal SDK 35, contemplate how lengthy it’s good to make the mandatory adjustments in your app.

In the event you want extra time to deal with insets to be suitable with the system’s default edge-to-edge habits, you’ll be able to briefly opt-out utilizing R.attr#windowOptOutEdgeToEdgeEnforcement. However do not plan to make use of this flag indefinitely as it is going to be non-functional within the close to future.

The flag may be notably useful for apps which have tens to lots of of Actions. You may opt-out every Exercise, then — make your app edge-to-edge one Exercise at a time.

Right here’s one strategy to utilizing this flag. Assuming your minSDK is lower than 35, this attribute have to be in values-v35.xml.




Create an empty fashion for previous variations in values.xml:




Name the fashion earlier than accessing the decor view in setContentView:

class MainActivity : AppCompatActivity() {
override enjoyable onCreate(savedInstanceState: Bundle?) {

// Name earlier than the DecorView is accessed in setContentView
theme.applyStyle(R.fashion.OptOutEdgeToEdgeEnforcement, /* power */ false)

tremendous.onCreate(savedInstanceState)
setContentView(R.format.activity_main)
...
}
}

Android 15 AOSP launched at the moment. Our workforce has created blogs, movies, and codelabs to assist get your app able to deal with the Android 15 edge-to-edge enforcement. What follows is an inventory of previous and new assets for additional studying.

Documentation

Deal with edge-to-edge enforcements in Android 15 (Compose)

LEAVE A REPLY

Please enter your comment!
Please enter your name here