androidmaterial-designandroid-jetpack-composeedge-to-edge

Compose: How to have ime padding and Scaffold padding with edge-to-edge and windowSoftInputMode is adjustResize


The androidx.compose.material3.Scaffold padding wrongly adds the Navigation Bar padding even when soft keyboard is open the IME padding is added, resulting in a double amount of Navigation Bar padding (see screenshot below, the divider should be touching the top of the soft keyboard).

I'm trying to have the following thing to work together:

  1. App is edge-to-edge
  2. windowSoftInputMode is adjustResize
  3. having my content inside a androidx.compose.material3.Scaffold

This is the code of the MainActivity:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)
        setContent {
            MyComposeApplicationTheme {
                Scaffold(
                    topBar = {
                        TopAppBar(
                            title = { Text(text = stringResource(id = R.string.app_name)) }
                        )
                    },
                ) { scaffoldPadding ->
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(scaffoldPadding),
                        contentAlignment = Alignment.BottomCenter
                    ) {
                        OutlinedTextField(
                            value = "",
                            onValueChange = {},
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(horizontal = 16.dp)
                        )
                        Divider()
                    }
                }
            }
        }
    }
}

And this is how it looks: enter image description here

But, if I open the keyboard, the screen does not resizes correctly, despite having the android:windowSoftInputMode="adjustResize" attribute inside the AndroidManifest set for the Activity: enter image description here

If I use the Modifier.imePadding(), the situation is improving but now I have, beside the padding for the IME, also the inner padding of the Scaffold that is taking into account the padding for the Navigation Bar even when the keyboard is open: enter image description here

What is the right way to keep the Scaffold bottom padding without it adding the Navigation Bar padding when the IME padding is added?

EDIT
I suspect this is a bug of the Scaffold so I've created an issue on the tracker: https://issuetracker.google.com/issues/249727298


Solution

  • Currently there is no clean solution but the following workaround seems to work fine: passing WindowInsets(0, 0, 0, 0) to Scaffold and then applying .padding(scaffoldPadding).consumedWindowInsets(scaffoldPadding).systemBarsPadding() internally, or applying imePadding() internally as well.

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            WindowCompat.setDecorFitsSystemWindows(window, false)
            setContent {
                MyComposeApplicationTheme {
                    Scaffold(
                        modifier = Modifier.imePadding(),
                        topBar = {
                            TopAppBar(
                                title = { Text(text = stringResource(id = R.string.app_name)) }
                            )
                        },
                        bottomBar = {
                            BottomAppBar() {
                                IconButton(onClick = { }) {
                                    Icon(Icons.Default.Build, null)
                                }
                            }
                        },
                        contentWindowInsets = WindowInsets(0, 0, 0, 0)
                    ) { scaffoldPadding ->
                        Box(
                            modifier = Modifier
                                .fillMaxSize()
                                .padding(scaffoldPadding)
                                .consumedWindowInsets(scaffoldPadding)
                                .systemBarsPadding(),
                            contentAlignment = Alignment.BottomCenter
                        ) {
                            OutlinedTextField(
                                value = "",
                                onValueChange = {},
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(horizontal = 16.dp)
    
                            )
                            Divider()
                        }
                    }
                }
            }
        }
    }