Now with Android Jetpack Compose released which is Android's modern UI toolkit , Bottomsheets can be made more easily without using any xml code:-
1.To create Persistent bottom sheet where user can access the content outside of the bottom sheet’s scope:-

val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)
val coroutineScope = rememberCoroutineScope()
MaterialTheme {
Column {
BottomSheetScaffold(
modifier = Modifier.fillMaxSize(),
topBar = { TopAppBar(viewModel, onNavigateToRecipeListScreen, hideKeyBoard) },
content = {
CreateRecipeContent(
viewModel,
context,
readExternalStorage,
bottomSheetScaffoldState,
coroutineScope
)
},
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
Column(
Modifier
.fillMaxWidth()
.height(200.dp)
.background(color = colorResource(id = R.color.colorPrimaryLight))
)
{
Text(
text = "SELECT PICTURE",
style = TextStyle(fontSize = 26.sp),
fontWeight = FontWeight.Bold,
modifier = Modifier
.padding(8.dp)
.align(Alignment.Start),
color = Color.Black
)
Spacer(modifier = Modifier.height(16.dp))
IconButton(onClick = {
when {
context.let { it1 ->
ContextCompat.checkSelfPermission(
it1,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} == PackageManager.PERMISSION_GRANTED -> {
val takePictureIntent =
Intent(MediaStore.ACTION_IMAGE_CAPTURE)
launchCamera(takePictureIntent)
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
else -> {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
viewModel.isCameraPermissionAsked = true
readExternalStorage()
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
}
}, modifier = Modifier.fillMaxWidth()) {
Text(
text = "TAKE PHOTO",
style = TextStyle(fontSize = 20.sp),
fontWeight = FontWeight.Bold,
modifier = Modifier
.padding(8.dp)
.align(Alignment.Start),
textAlign = TextAlign.Left,
color = Color.Black
)
}
Spacer(modifier = Modifier.height(16.dp))
IconButton(onClick = {
when {
context.let { it1 ->
ContextCompat.checkSelfPermission(
it1,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} == PackageManager.PERMISSION_GRANTED -> {
val galleryIntent = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
galleryIntent.type = "image/*"
launchGalley(galleryIntent)
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
else -> {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
viewModel.isCameraPermissionAsked = false
readExternalStorage()
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.collapse()
}
}
}
}, modifier = Modifier.fillMaxWidth()) {
Text(
text = "CHOOSE FROM GALLERY",
style = TextStyle(fontSize = 20.sp),
fontWeight = FontWeight.Bold,
modifier = Modifier
.padding(8.dp)
.align(Alignment.Start),
textAlign = TextAlign.Left,
color = Color.Black
)
}
}
}, sheetPeekHeight = 0.dp
)
}
}
Above code snipped and screenshot is from the app:-
https://play.google.com/store/apps/details?id=com.bhuvnesh.diary
created entirely using Jetpack Compose by me
To create Modal Bottom Sheet where users cannot access the content out of the bottom sheet’s scope:-
ModalBottomSheetLayout(
sheetState = modalBottomSheetState,
sheetElevation = 8.dp,
sheetContent = {
//sheet content
}
) {
...
//main content
}