Reputation: 1123
Hello I am trying to create a modal bottom sheet with several input fields. Whatever I tried it didn't show the content above the keyboard. Here is my code:
Firstly I set my activity to have:
android:windowSoftInputMode="adjustResize"
Then my composables:
interface DialogCallback {
fun dismissDialog(onDismissed: () -> Unit)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppBottomSheet(
modifier: Modifier = Modifier,
title: String? = null,
content: @Composable ColumnScope.(DialogCallback) -> Unit,
scope: CoroutineScope = rememberCoroutineScope(),
state: SheetState? = null,
hasTitleSeparator: Boolean = true,
onDismissed: () -> Unit,
) {
// For preview purposes.
val sheetState = state ?: rememberModalBottomSheetState(skipPartiallyExpanded = true)
fun dismissSmoothly(onSmoothDismissed: () -> Unit) {
scope
.launch { sheetState.hide() }
.invokeOnCompletion {
Log.d("BottomSheetDismiss", "Dismissed ${sheetState.isVisible}")
if (!sheetState.isVisible) {
onSmoothDismissed()
}
}
}
BackHandler {
dismissSmoothly {
onDismissed()
}
}
ModalBottomSheet(
modifier = modifier,
shape = ShapesTopOnly.large,
onDismissRequest = {
onDismissed()
},
sheetState = SheetState(
skipPartiallyExpanded = true,
density = LocalDensity.current,
initialValue = SheetValue.Expanded,
),
dragHandle = {},
properties = ModalBottomSheetDefaults.properties(shouldDismissOnBackPress = true, isFocusable = true),
windowInsets = WindowInsets.navigationBars,
) {
// Title.
if (title != null) {
AppBottomSheetHeader(
text = title,
onClicked = {
dismissSmoothly {
onDismissed()
}
},
)
}
// Divider.
if (hasTitleSeparator) {
AppGenericDivider()
}
// Content of the bottom sheet.
content(
object : DialogCallback {
override fun dismissDialog(onDismissed: () -> Unit) {
dismissSmoothly {
onDismissed()
}
}
}
)
if (Build.VERSION.SDK_INT < 30)
Spacer(modifier = Modifier.padding(bottom = BOTTOM_NAVIGATION_BAR_PADDING))
}
}
Calling my AppBottomSheet:
var field1 by remember { mutableStateOf("") }
var field2 by remember { mutableStateOf("") }
var field3 by remember { mutableStateOf("") }
AppBottomSheet(
title = title,
state = sheetState,
hasTitleSeparator = false,
onDismissed = {
onDismissed(null, null, null)
},
content = { callback ->
ProvideWindowInsets(consumeWindowInsets = true) {
Column(
modifier.navigationBarsWithImePadding()
) {
OutlinedTextField(value = field1, onValueChange = {field1 = it})
OutlinedTextField(value = field2, onValueChange = {field2 = it})
OutlinedTextField(value = field3, onValueChange = {field3 = it})
TextButton(
modifier = Modifier.padding(top = 40.dp),
onClick = {
showBottomSheet = false
}) {
Text(text = "DISMISS")
}
}
}
},
)
Upvotes: 0
Views: 679
Reputation: 1
I hope it’s not too late with an answer and I will help other people who have encountered such a problem, the point is that the android:windowSoftInputMode="adjustResize"
tag
it helps if you use no more than 1 view, but if you have several OutlinedTextFields, then the screen will still overlap, this article describes this case in detail
https://medium.com/@mark.frelih_9464/how-to-handle-automatic-content-resizing-when-keyboard-is-visible-in-jetpack-compose-1c76e0e17c57
If you have ModalBottomSheet, then you can easily monitor the state of the keyboard as follows:
val keyboardHeight = WindowInsets.ime.getBottom(LocalDensity.current)
and then change the state
onExpandState = {keyBoardIsOpen ->
scope.launch {
if(keyBoardIsOpen)
sheetState.expand()
else
sheetState.partialExpand()
}
}
Upvotes: 0