Hi all, I'm having an issue with compose, status b...
# compose
m
Hi all, I'm having an issue with compose, status bar padding and the soft keyboard. I'll put the code in the thread, but in short, when the soft keyboard is coming up, in order to keep the focused text field in view, it's shifting all the other content up, and it ends up under the status bar. I have tried adjusting the soft window input mode to other things, but I can't really find a decent option. Ideally i'd want the part under the status bar to not be visible. But in this example, you can see that the blue block (a placeholder for a real image in our production code) is going under the status bar making it unreadable depending on what color that block is.
Copy code
import androidx.activity.*
import androidx.activity.compose.LocalActivity
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

@Composable
@Preview
fun ImeStatusBarIssue() {
    MaterialTheme {
        val activity = LocalActivity.current
        SideEffect {
            (activity as? ComponentActivity)?.let {
                it.enableEdgeToEdge(
                    statusBarStyle = SystemBarStyle.light(Color.Transparent.toArgb(), Color.Transparent.toArgb()),
                    navigationBarStyle = SystemBarStyle.light(Color.Transparent.toArgb(), Color.Transparent.toArgb())
                )
            }
        }

        Scaffold { contentPadding ->
            Column(modifier = Modifier.padding(contentPadding)) {
                Column(
                    modifier = Modifier.weight(1f, true),
                    verticalArrangement = spacedBy(16.dp)
                ) {
                    Image(
                        modifier = Modifier.fillMaxWidth().height(400.dp),
                        painter = ColorPainter(Color.Blue),
                        contentDescription = null
                    )

                    Text(text = "Title", style = MaterialTheme.typography.headlineLarge)

                    Text(text = "Subtitle", style = MaterialTheme.typography.bodyLarge)

                    var text1 by remember { mutableStateOf("") }
                    OutlinedTextField(
                        label = { Text("Text1") },
                        placeholder = { Text("Enter Text") },
                        value = text1,
                        onValueChange = { text1 = it }
                    )

                    var text2 by remember { mutableStateOf("") }
                    OutlinedTextField(
                        label = { Text("Text2") },
                        placeholder = { Text("Enter Text") },
                        value = text2,
                        onValueChange = { text2 = it }
                    )

                }

                Button(
                    modifier = Modifier.fillMaxWidth(.5f).align(Alignment.CenterHorizontally),
                    onClick = { }
                ) {
                    Text("Click Me")
                }
            }
        }
    }
}
a
That looks like
adjustPan
behavior - what does
adjustResize
give you?
m
Use imePadding for keyboard and displayCutoutPadding for status bar. These are modifiers you can use anywhere
m
If I use adjustResize (which is deprecated by the way), it doesn't really moving anything, and the text field gets obscured. Also manually using the padding does nothing, as the M3 Saffold function automatically should be handling all the insets for me, and it does, other than the case where the keyboard is on screen
@Alex Vanyo Is there a way to maybe monitor the offset? I presume that the default behavior above is produced by changing the offset of the screen content so that the Y offset is some negative value. I'm wondering if i can monitor that, and detect when the image overlaps the status bar and then set the status bar to dark instead of light. Otherwise, i'm not really sure how to fix this.
m
@mattinger Did you try .imePadding modifier?
a
(which is deprecated by the way)
You should be able to use
adjustNothing
on API 30+, and
adjustResize
on API 29 and below, with the combination of handling insets directly.
Scaffold
does handle most types of insets directly by default, but it explicitly doesn’t handle ime insets by default - the reason for this is that it ends up being weird of bottom bars end up being adjust for insets. Adding `adjustResize`/`adjustNothing` and adding
imePadding()
or including
WindowInsets.ime
in the insets that
Scaffold
does take into account should do the trick
I’m wondering if i can monitor that, and detect when the image overlaps the status bar and then set the status bar to dark instead of light. Otherwise, i’m not really sure how to fix this.
adjustPan
is really hard for apps to handle directly - the best way to do the above is to switch to
adjustResize
and get that information with the inset APIs