How can I implement Bottom sheet with BottomBar in jetpack compose

2.3k Views Asked by At

So what I am trying to achieve is:

  • A home composable that hosts a BottomNav Bar (Scaffold is used here )
  • Bottom Nav Bar is attached with 3 other composables
  • Each of the 3 composables has its own lazy column
  • Every item in the 3 lazy columns have a menu icon which when clicked opens the bottom sheet

I was able to achieve the above by enclosing the scaffold inside a ModalBottonSheetLayout with the help of this answer here: Jetpack Compose Scaffold + Modal Bottom Sheet

The issue:

  • The purpose of the bottom sheet is to show a menu item which when clicked should delete the item from the lazyColumn
  • so the bottom sheet needs to know the details of the item that was clicked to delete it

How can I achieve that? The home composable does not have any information about the items inside the lazy columns present in the composables that it hosts.

Is there a different way to approach this?

Here is my code:

HomeComposable.kt

fun HomeComposable(homeViewModel: HomeViewModel, 
     navController: NavHostController) {
        ModalBottomSheetLayout(
           sheetContent = {
           //get the id of the message here so it can be     
           //deleted
               Button(
                   text = "delete Message")
                   onClick = deleteMessage(message.id
               )
           }
) {
    Scaffold(
    content = {
    NavHost(navController = navController, startDestination = 
    WHATS_NEW_COMPOSABLE) {

          composable(MESSAGES_COMPOSABLE) {
            MessageItemsComposable(
                homeViewModel,
                navController,
                bottomSheetState
            )
          }
 
    }
  }  
)

MessageItemsComposable.kt

val messages : List<Messages> = getMessagesFromNetwork()

LazyColumn {
    items(messages) { message ->
    Row{
        Text(message.title)
        Icon(
            onClick = {
             bottomState.show()
             //show a bottom sheet with an option to delete                 
            }
        ) {

           //Draw the icon
           }
        }            
    }
}
1

There are 1 best solutions below

2
On

For that case, I would use a repository with a StateFlow. This repository would be a singleton and it's responsible of maintaining data and deleting them. Your composable list will listen to state changes and your bottomsheet will call delete() to delete the selected element.

class Repository<T> {
    private val _state = MutableStateFlow<T>(initialState)
    val state: StateFlow<T> = _state

    fun delete(data: T) {
        _state.remove(data)
    }
}

The parent of you composable list should provide a callback. This callback should be invoked when the user clicks on a list item and that item is passed as parameter.

@Composable
fun DataList(onItemClick(item: T)) {
    // list implementation with onItemCkick as onClick callback
}

When invoked, you can open the bottomsheet and pass the item to it.