Reputation: 347
I have a pinned bottom container with a textfield. And i use imePadding modifier. When keyboard appears seems like imePadding works twice. It happens only on some devices. Particular my is Samsung Galaxy A80 (Android 11)
Code example
Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
Box(
Modifier
.imePadding()
.height(100.dp)
.background(Color.Red),
) {
BasicTextField(
modifier = Modifier.fillMaxWidth(),
value = "some text",
onValueChange = {},
)
}
},
) {
Box(
Modifier.fillMaxSize().padding(bottom = it.calculateBottomPadding()),
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
) {
repeat((0..100).count()) {
item {
Box(Modifier.fillMaxWidth().height(100.dp).background(Color.Blue)) {
}
}
}
}
}
}
UPD Issue reproduce when I add:
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
Upvotes: 15
Views: 9159
Reputation: 1352
I've implemented a custom modifier that adjusts the padding of a composable based on its position relative to the bottom of the window. This is useful for ensuring that the composable doesn't get covered by the keyboard (IME) when it appears, especially when imePadding() doesn't behave as expected on some devices.
Here’s the modifier:
fun Modifier.positionAwareImePadding() = composed {
var consumePadding by remember { mutableIntStateOf(0) }
this@positionAwareImePadding
.onGloballyPositioned { coordinates ->
val rootCoordinate = coordinates.findRootCoordinates()
val bottom = coordinates.positionInWindow().y + coordinates.size.height
consumePadding = (rootCoordinate.size.height - bottom).toInt()
}
.consumeWindowInsets(PaddingValues(bottom = consumePadding.pxToDp()))
.imePadding()
}
How it works:
This modifier is particularly useful for handling IME (keyboard) positioning issues on devices where imePadding() alone may not work reliably.
For more information about handling Edge-to-edge and insets: https://www.youtube.com/watch?v=QRzepC9gHj4
Upvotes: 3
Reputation: 166
I also had this issue; more specifically, some devices would seem to ignore adjustResize, but adding imePadding alongside adjustResize would cause others to double it up.
I solved it for myself in the following way:
android:windowSoftInputMode="adjustNothing"
consumeWindowInsets(contentPadding)
on the Modifier of those contents, before imePadding, otherwise the contentPadding got consumed additively in the imePadding.Something like:
Scaffold(...){ contentPadding ->
Box(
modifier = Modifier
.padding(contentPadding)
.consumeWindowInsets(contentPadding)
.imePadding()
){...}
}
I can't guarantee that this is best practice or that it works in all cases, but it worked for me.
Upvotes: 15
Reputation: 207
add this line to activity in AndroidManifest.xml file android:windowSoftInputMode="adjustResize"
. The activity's layout will be resized to ensure that all of its visible content remains visible even when the soft keyboard is shown without using any imePadding()
modifiers.
here you can see improved code.
var value by remember { mutableStateOf("") }
Scaffold(
bottomBar = {
Box(modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface)) {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(), value = value,
onValueChange = { value = it }
)
}
},
) { paddingValues ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentPadding = PaddingValues(12.dp, 16.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
items(100) {
Card(modifier = Modifier.fillMaxSize()) {
Text(text = "Item $it", modifier = Modifier.padding(8.dp))
}
}
}
}
Upvotes: 0