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

5.8k Views Asked by At

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

2

There are 2 best solutions below

2
Roberto Leinardi On BEST ANSWER

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()
                    }
                }
            }
        }
    }
}
0
Alessandro Verrecchia On

Whenever the keyboard opens up, for some reasons the values in scaffoldPadding are erroneous.

I have a TopBar but not a BottomBar. ScaffoldPadding value should be :

  • Top:64
  • Bottom:0
  • Start:0
  • End:0

But are (only after the keyboard was opened) :

  • Top:64
  • Bottom:48 (the bug ?)
  • Start:0
  • End:0

Personally to fix my issue of having en extra bottom padding in the Scaffold is not to apply the given scaffoldPadding.

        Scaffold(
        snackbarHost = { ...},
        topBar = { ...},
        content = { scaffoldPadding ->
            Box(
                modifier = Modifier.padding(top = scaffoldPadding.calculateTopPadding())
            ) {
               ...
            }
        }
    )