Im working with Jetpack Compose and having a ModalBottomSheetLayout with a TextField. While Closing the bottom sheet, the keyboard it not going off.
Keyboard should hide, when ModalBottomSheetLayout dismisses.
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun ModalBottomSheetSample() {
val state = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden,)
val scope = rememberCoroutineScope()
BackHandler(state.isVisible) {
scope.launch {state.hide()}
}
ModalBottomSheetLayout(sheetState = state, sheetContent = {
TextField(value = "",
onValueChange = {},
placeholder = { Text(text = "Search") },
modifier = Modifier
.padding(10.dp)
.fillMaxWidth()
)
LazyColumn {items(50) {...}}
}) {
Button(onClick = { scope.launch { state.show() } }) {
Text("Click to show sheet")
}
}
}
have referred this question, but this is not applicable for this scenario. As this is based on Composable.
Related
I have a strange UI glitch for the keyboard when the ModalBottomSheetLayout is in expanded state and the keyboard appears.
#Composable
#OptIn(ExperimentalMaterialApi::class)
fun ModalBottomSheetSample() {
val state = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden, skipHalfExpanded = true)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetState = state,
sheetContent = {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
repeat(20) {
TextField(value = "", onValueChange = {})
}
}
}
) {
Button(onClick = { scope.launch { state.show() } }) {
Text("Click to show sheet")
}
}
}
and here is a video: https://drive.google.com/file/d/1IMU4kGY3hnixK6bVME1iqH0aPDe4-hjr/view?usp=sharing
Anyone any idea how to fix this?
I want to use
When the user arrives on the page, the bottomsheet pops at the top of the screen before beeing dragged down to the bottom of the screen (where it is supposed to be)
Here is a code that reproduces the issue :
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun testBottomsheet(){
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
drawerState = rememberDrawerState(DrawerValue.Open),
bottomSheetState = BottomSheetState(BottomSheetValue.Expanded),
)
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
Box(
Modifier
.fillMaxWidth()
.height(200.dp)
) {
Text(text = "Hello from sheet")
}
}, sheetPeekHeight = 0.dp
) {
Button(onClick = {
}) {
Text(text = "Expand/Collapse Bottom Sheet")
}
}
}
Upon clicking a FAB, the app opens a Dialog with a camera icon in it, including text fields. Clicking the icon does not open the ModalBottomSheetLayout inside the Dialog as it should; It opens it in the parent screen that contains the FAB. How can make it open inside the Dialog?
Screen Recording
Main Screen Composable:
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun AddItemDialogWithModalSheet(
onDismiss: () -> Unit,
) {
val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetContent = {
Column() {
Text(text = "Testing")
Text(text = "Testing")
Text(text = "Testing")
Text(text = "Testing")
Text(text = "Testing")
Text(text = "Testing")
}
},
sheetState = sheetState,
) {
AddItemDialog(
onConfirmClicked = { /*TODO*/ },
onDismiss = onDismiss,
onCameraClick = {
scope.launch {
sheetState.show()
}
}
)
}
}
Dialog Composable:
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun AddItemDialog(
onConfirmClicked: () -> Unit,
onDismiss: () -> Unit,
onCameraClick: () -> Unit
) {
val nameText = rememberSaveable { mutableStateOf("") }
val quantityText = rememberSaveable { mutableStateOf("") }
val unitText = rememberSaveable { mutableStateOf("") }
val ppuText = rememberSaveable { mutableStateOf("") }
val notesText = rememberSaveable { mutableStateOf("") }
var categoryText = rememberSaveable { mutableStateOf("") }
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(usePlatformDefaultWidth = false),
) {
Surface(
shape = MaterialTheme.shapes.medium,
color = MaterialTheme.colors.surface,
modifier = Modifier
.width(LocalConfiguration.current.screenWidthDp.dp * 0.96f)
.padding(4.dp)
) {
...
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()
.requiredHeight(70.dp)
.padding(10.dp)
) {
Icon(
painterResource(id = R.drawable.ic_baseline_photo_camera_24),
contentDescription = "Add Item Picture",
modifier = Modifier
.size(40.dp).clickable(onClick = {
onCameraClick() //this code does not open the bottom sheet
})
)
}
}
}
}
I don't think this is a good idea in terms of UX.
My suggestion is follow the Material Design guidelines and use the Full Screen Dialog. See what the documentation says:
Full-screen dialogs may be used for content or tasks that meet any of
these criteria:
Dialogs that include components which require keyboard input, such as form fields;
When changes aren’t saved instantly;
When components within the dialog open additional dialogs.
Your UI matches all the criteria to use a full-screen dialog.
I'm having some issues with ModalBottomSheetLayout trying to make it fully expanded. I tried some answers from other posts (like Make ModalBottomSheetLayout always Expanded) with no result.
This is the Composable function I've created:
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun ExpandedSheetDialog(
sheetContent: #Composable (() -> Unit),
screenContent: #Composable (() -> Unit),
modalState: ModalBottomSheetState
) {
ModalBottomSheetLayout(
sheetState = modalState,
sheetShape = RoundedCornerShape(topEnd = 10.dp, topStart = 10.dp),
sheetContent = { sheetContent.invoke() },
content = { screenContent.invoke() }
)
}
And this is the Preview:
#OptIn(ExperimentalMaterialApi::class)
#Preview(showBackground = true)
#Composable
fun ExpandedSheetDialogPreview() {
val scope: CoroutineScope = rememberCoroutineScope()
val modalSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Expanded)
ExpandedSheetDialog(
sheetContent = {
Button(
onClick = {
scope.launch {
modalSheetState.animateTo(ModalBottomSheetValue.Hidden)
}
},
text = "Hide"
)
},
screenContent = {
Column(
modifier = Modifier.padding(16.dp).fillMaxHeight(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(
onClick = {
scope.launch {
modalSheetState.animateTo(ModalBottomSheetValue.Expanded)
}
},
text = "Show Extended"
)
}
},
modalState = modalSheetState
)
}
I tried in several emulators, all of them with the same result, the "BottomSheetDialog" appears but is not fully expanded. What am I doing wrong?
I currently display a Bottom Sheet through a BottomSheetScaffold and want to collapse it when the user clicks outside the Bottom Sheet. Is there a way to detect the click outside of the Bottom Sheet?
This is the screen with my BottomSheetScaffold:
#ExperimentalMaterialApi
#ExperimentalMaterial3Api
#Composable
fun HomeScreen() {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)
val coroutineScope = rememberCoroutineScope()
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
Box(
Modifier
.fillMaxWidth()
.fillMaxHeight(0.9f)
) {
Text("Hello from Sheet")
}
},
sheetShape = RoundedCornerShape(
topStart = Spacing.l,
topEnd = Spacing.l
),
sheetPeekHeight = LocalConfiguration.current.screenHeightDp.dp * 0.15f,
sheetBackgroundColor = MaterialTheme.colorScheme.surface,
) {
Scaffold() {
Button(
onClick = {
coroutineScope.launch {
if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
bottomSheetScaffoldState.bottomSheetState.expand()
} else {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
},
) {
Text("Toggle Sheet")
}
}
}
}
This is a visualization of the area in which I want to detect the click if the Bottom Sheet is expanded.
You can add the pointerInput modifier with detectTapGestures to your Scaffold:
Scaffold( modifier =
Modifier.pointerInput(Unit) {
detectTapGestures(onTap = {
coroutineScope.launch {
if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
bottomSheetScaffoldState.bottomSheetState.expand()
} else {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
})
}){
//.....
}
I had the same problem using the BottomSheetScaffold, and I changed to the ModalBottomSheetLayout that already has that behavior by default.
I hope this could help anybody with the same problem