Ali Yucel Akgul
Ali Yucel Akgul

Reputation: 1123

Jetpack Compose Modal Bottom Sheet never shows OutlinedTextField form

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

Answers (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

Related Questions