@@ -28,9 +28,12 @@ import androidx.compose.foundation.layout.PaddingValues
28
28
import androidx.compose.foundation.layout.Spacer
29
29
import androidx.compose.foundation.layout.WindowInsets
30
30
import androidx.compose.foundation.layout.WindowInsetsSides
31
+ import androidx.compose.foundation.layout.asPaddingValues
31
32
import androidx.compose.foundation.layout.consumeWindowInsets
33
+ import androidx.compose.foundation.layout.fillMaxSize
32
34
import androidx.compose.foundation.layout.ime
33
35
import androidx.compose.foundation.layout.imePadding
36
+ import androidx.compose.foundation.layout.navigationBars
34
37
import androidx.compose.foundation.layout.only
35
38
import androidx.compose.foundation.layout.padding
36
39
import androidx.compose.foundation.layout.safeDrawingPadding
@@ -44,10 +47,16 @@ import androidx.compose.material3.ExperimentalMaterial3Api
44
47
import androidx.compose.material3.LargeTopAppBar
45
48
import androidx.compose.material3.Scaffold
46
49
import androidx.compose.material3.Text
50
+ import androidx.compose.material3.TextField
47
51
import androidx.compose.runtime.Composable
52
+ import androidx.compose.ui.Alignment.Companion.BottomCenter
48
53
import androidx.compose.ui.Modifier
54
+ import androidx.compose.ui.layout.WindowInsetsRulers
55
+ import androidx.compose.ui.layout.layout
49
56
import androidx.compose.ui.tooling.preview.Preview
57
+ import androidx.compose.ui.unit.Constraints
50
58
import androidx.compose.ui.unit.dp
59
+ import kotlin.math.roundToInt
51
60
52
61
class InsetSnippetActivity : ComponentActivity () {
53
62
@@ -147,3 +156,55 @@ fun OverrideDefaultInsetsSnippet() {
147
156
)
148
157
// [END android_compose_insets_override_defaults]
149
158
}
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