skip to Main Content

Using Material3 design principle, I think (I may be wrong here) BottomSheetScaffold Composable should be used rather than ModalBottomSheet Composable, but the problem is that I didn’t find any way of using it with Bottom Navigation Bar.

Also, I could not control the visibility of the two different composable functions i.e. Now Playing screen when BottomSheet is expanded and Mini-Player when the BottomSheet is partially collapsed.

What is the recommended practice? Is there any other way to achieve this behavior or this is the one? If this is the way than how can I do it?

Just for more context, there is no bottomBar parameter in the BottomSheetScaffold like topBar to pass the Bottom Navigation Bar.

// there is no bottomBar parameter like topBar

BottomSheetScaffold(
    scaffoldState = scaffoldState,
    sheetContent = {
        // This is where I want to have isExpanded condition to show mini-player or Now Playing screen
        MyExpandedPlayerSampleScreen()
        // Adding Bottom Navigation Bar here didn't work as expected
    },
    sheetPeekHeight = 72.dp,
    sheetSwipeEnabled = true,
    topBar = {
        ExitUntilCollapsedLargeTopAppBar(
            scrollBehavior = scrollBehavior
        )
    },
    modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
) { innerPadding ->
    FakeListItemsWithState(
        paddingValues = innerPadding,
        lazyListState = listState,
        modifier = Modifier
    )
}

Edit:
Here, I have attached an image and a short video of the behavior I want to achieve.

I want to have bottom sheet peek the required space on top of the bottom navigation bar and respond accordingly with respect the bottom sheet expansion.
I want Bottom Navigation Bar to exitOnBottomSheetExpand. (like in YouTube and YouTube Music App)

(Just to be clear, YouTube uses their custom bottom bar. However, many modern music player app uses Bottom Navigation Bar with bottom sheet to achieve this Layout/behavior.)

2

Answers


  1. Thanks for asking the question. I am sorry for that, if I may misunderstood your question. What I had understood is that, You have to implement bottomSheet with bottom navigation, right. If this is your problem, I would recommend using Scaffold + ModalBottomSheetLayout. This is my personal go to approach. It gives more control over customize bottom sheet and I can use bottom navigation.
    Here is one of my code’s composable, where I had implemented it.
    Some clarification regarding my sample composable->

    1. BottomSheetStructure() composable = It is the composable(in my code) that handles modal bottom sheet layout. I would share that also for more clarity.

    2. TopBar = It is responsible for top bar of my screen. Same goes with BottomBar composable and DrawerItem composable , they manages bottom navigation and drawer item respectively.

        @OptIn(ExperimentalMaterialApi::class)
        @Composable
        fun MainView(
            onNavigateToDrawerItem: (Screens.DrawerScreen) -> Unit,
            onNavigateToSheetItem: (Screens.BottomSheetScreen) -> Unit,
            onNavigateToBottomBarItem: (Screens.BottomScreen) -> Unit,
            onNavigateToRegisterScreen: () -> Unit,
            onNavigateToProfileScreen:() -> Unit
        ){
      
       val sheetState = rememberModalBottomSheetState(
           initialValue = ModalBottomSheetValue.Hidden,
           confirmValueChange = {//It will change the value of sheetstate when it is half expanded
               it != ModalBottomSheetValue.HalfExpanded
           }
       )
      
       BottomSheetStructure(
           sheetState = sheetState,
           onNavigateToSheetItem ={
               item->
               onNavigateToSheetItem(item)
           } ,
           sheetContent = {
               //Since opening and closing of drawer is a coroutine function 
                therefore scope is required
           val scope: CoroutineScope = rememberCoroutineScope()
      
           //To manage the state of Scaffold
           val scaffoldState: ScaffoldState = rememberScaffoldState()
      
      
           //For viewModel
           val viewModel:UserDetailViewModel = viewModel()
      
      
      
      
      
      
      
      
           Scaffold (
               scaffoldState = scaffoldState,
      
               topBar = {
                   TopBar(
                       title = "Home",
                       scope,
                       scaffoldState,
                       sheetState,
                       onNavigateToRegisterScreen = {onNavigateToRegisterScreen()},
      
                       onNavigateToProfileScreen = {onNavigateToProfileScreen()}
                   )
                        },
               bottomBar = { BottomBar(onNavigateToBottomBarItem={
                   onNavigateToBottomBarItem(it)
               })},
               drawerContent = {
                   LazyColumn{
                       items(screensInDrawer){
                               item ->
                           DrawerItem(
                               selected = false,
                               onDrawerItemClicked = {
                                   onNavigateToDrawerItem(item)
      
                                   scope.launch {
                                       scaffoldState.drawerState.close()
                                   }
                               },
                               item =item
                           )
                       }
                   }
               }
           )
           {
               Column {
                   Text(text = "This is home", Modifier.padding(it))
               }
           }
       }
      

      )

    }

    1. BottomSheetStructure.kt (Just for reference on how can you use Modal bottom sheet layout with scaffold)->

       @OptIn(ExperimentalMaterialApi::class)
       @Composable
       fun BottomSheetStructure(
           onNavigateToSheetItem:(Screens.BottomSheetScreen) -> Unit,
           sheetState: ModalBottomSheetState ,
           sheetContent: @Composable ()-> Unit
        ){
            //Making for modifier variable for Modal Bottom Sheet Layout
            val isSheetFullScreen by remember {
                mutableStateOf(false)
            }
      
      
       //To give border radius to ModalBottomSheet
       val roundedCornerRadius = if(isSheetFullScreen) 0.dp else 12.dp
      
      
       ModalBottomSheetLayout(
           sheetState = sheetState,
           sheetShape = RoundedCornerShape(topStart = roundedCornerRadius, topEnd = roundedCornerRadius),
           sheetContent = {
               LazyColumn{
                   items(screensInBottomSheet){
                           item ->
                       BottomSheetContent(
                           item = item,
                           onBottomSheetItemClicked = {
                               //TODO
                               onNavigateToSheetItem(item)
                           }
                       )
      
                   }
               }
      
           }
       ){
           sheetContent()
       }
       }
      

    I hope this approach will help if. If you have any other doubt regarding this or any doubt about jetpack or other android components , feel free to ask. I would love to answer it.
    Thanks

    Login or Signup to reply.
  2. Have you done it? I also want to achieve this. Got the same problem as you

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search