How to prevent a jetpack compose scaffold from taking the whole height of the screen when it is shown in a dialog

Viewed 1330

I am having an android activity which has Base.Theme.AppCompat.Light.Dialog as a theme on tablets and therefore is shown in a dialog.

When I used XML layouts I could set a min height with wrap content for the layout so it would

  • Be at least x dp high when there was no or very little content.
  • High as the content when the content was higher than the min height
  • High as the screen when the content wouldnt fit inside the height of the screen, in that case I could scroll

Using a Jetpack Compose's Scaffold I am struggling recreating that behaviour. The dialog is alsways as high as the screen allows, even when there is no content.

I tried the following modifiers as a parameter to the scaffold:

  • Modifier.wrapContentHeight() - the dialog is still as high as the screen
  • Modifier.defaultMinSize(minHeight = 250.dp) - the dialog is still as high as the screen
  • Modifier.height(height = 250.dp) - now it is smaller but it is fixed to that size, not growing when there is more content
  • Modifier.requiredHeightIn(min = 250.dp, max = getMyScreenHeightinDp()) - the dialog is still as high as the screen

Since you can reduce the height of the scaffold with the .height(...) modifier I think it should also be possible to recreate a wrap content behaviour. But how?

1 Answers

Using requiredHeightIn does work, as tested in the code below. In this list, the height varies from 150.dp to 400.dp. If you only provide 10 items, it will be 150.dp. As you add more items, it increases in height but only to a maximumo of 400.dp.

However, there is a catch. The navigation drawer slides out from the left side of the screen and not the left side of the dialog. There are ways around that. You could replace the navigation drawer with your own custom drawer. I did this once and it can be done.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startActivity(intent)

        setContent {

            Dialog(
                onDismissRequest = {  },
                properties = DialogProperties(dismissOnClickOutside = false)
            ) {
                val scaffoldState = rememberScaffoldState()
                val scope = rememberCoroutineScope()
                Scaffold(
                    modifier = Modifier.requiredHeightIn(min = 150.dp, max = 400.dp),
                    scaffoldState = scaffoldState,
                    drawerContent = { Text("Drawer content") },
                    topBar = {
                        TopAppBar(
                            title = { Text("Simple Scaffold Screen") },
                            navigationIcon = {
                                IconButton(
                                    onClick = {
                                        scope.launch { scaffoldState.drawerState.open() }
                                    }
                                ) {
                                    Icon(Icons.Filled.Menu, contentDescription = "Localized description")
                                }
                            }
                        )
                    },
                    floatingActionButtonPosition = FabPosition.End,
                    floatingActionButton = {
                        ExtendedFloatingActionButton(
                            text = { Text("Inc") },
                            onClick = { /* fab click handler */ }
                        )
                    },
                    content = { innerPadding ->
                        LazyColumn(contentPadding = innerPadding) {
                            items(count = 100) {
                                Text(it.toString())

                            }
                        }
                    }
                )
            }
        }
    }
}
Related