@@ -28,9 +28,12 @@ import androidx.compose.foundation.layout.PaddingValues
2828import androidx.compose.foundation.layout.Spacer
2929import androidx.compose.foundation.layout.WindowInsets
3030import androidx.compose.foundation.layout.WindowInsetsSides
31+ import androidx.compose.foundation.layout.asPaddingValues
3132import androidx.compose.foundation.layout.consumeWindowInsets
33+ import androidx.compose.foundation.layout.fillMaxSize
3234import androidx.compose.foundation.layout.ime
3335import androidx.compose.foundation.layout.imePadding
36+ import androidx.compose.foundation.layout.navigationBars
3437import androidx.compose.foundation.layout.only
3538import androidx.compose.foundation.layout.padding
3639import androidx.compose.foundation.layout.safeDrawingPadding
@@ -44,10 +47,16 @@ import androidx.compose.material3.ExperimentalMaterial3Api
4447import androidx.compose.material3.LargeTopAppBar
4548import androidx.compose.material3.Scaffold
4649import androidx.compose.material3.Text
50+ import androidx.compose.material3.TextField
4751import androidx.compose.runtime.Composable
52+ import androidx.compose.ui.Alignment.Companion.BottomCenter
4853import androidx.compose.ui.Modifier
54+ import androidx.compose.ui.layout.WindowInsetsRulers
55+ import androidx.compose.ui.layout.layout
4956import androidx.compose.ui.tooling.preview.Preview
57+ import androidx.compose.ui.unit.Constraints
5058import androidx.compose.ui.unit.dp
59+ import kotlin.math.roundToInt
5160
5261class InsetSnippetActivity : ComponentActivity () {
5362
@@ -147,3 +156,55 @@ fun OverrideDefaultInsetsSnippet() {
147156 )
148157 // [END android_compose_insets_override_defaults]
149158}
159+
160+ // [START android_compose_insets_rulers]
161+ @Composable
162+ fun WindowInsetsRulersDemo (modifier : Modifier ) {
163+ Box (
164+ contentAlignment = BottomCenter ,
165+ modifier = modifier
166+ .fillMaxSize()
167+ // The mistake that causes issues downstream, as .padding doesn't consume insets.
168+ // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars),
169+ // assume it's difficult to identify this issue to see how WindowInsetsRulers can help.
170+ .padding(WindowInsets .navigationBars.asPaddingValues())
171+ ) {
172+ TextField (
173+ value = " Demo IME Insets" ,
174+ onValueChange = {},
175+ modifier = modifier
176+ // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child
177+ // Composable without having to fix the parent upstream.
178+ .alignToSafeDrawing()
179+
180+ // .imePadding()
181+ // .fillMaxWidth()
182+ )
183+ }
184+ }
185+
186+ fun Modifier.alignToSafeDrawing (): Modifier {
187+ return layout { measurable, constraints ->
188+ if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) {
189+ val placeable = measurable.measure(constraints)
190+ val width = placeable.width
191+ val height = placeable.height
192+ layout(width, height) {
193+ val bottom = WindowInsetsRulers .SafeDrawing .current.bottom
194+ .current(0f ).roundToInt() - height
195+ val right = WindowInsetsRulers .SafeDrawing .current.right
196+ .current(0f ).roundToInt()
197+ val left = WindowInsetsRulers .SafeDrawing .current.left
198+ .current(0f ).roundToInt()
199+ measurable.measure(Constraints .fixed(right - left, height))
200+ .place(left, bottom)
201+ }
202+ } else {
203+ val placeable = measurable.measure(constraints)
204+ layout(placeable.width, placeable.height) {
205+ placeable.place(0 , 0 )
206+ }
207+ }
208+ }
209+ }
210+ // [END android_compose_insets_rulers]
0 commit comments