2

So i am new to Jetpack compose and am trying to figure out how to add the drawer functionality to a button on my view.

A counterpart question that i found for my question in relation to the XML imperative approach Navigation Drawer without Actionbar

Would love to learn about the approach to the same.

Gaurav Sarma
  • 2,248
  • 2
  • 24
  • 45

2 Answers2

0

You can use Scaffold and configure only the drawer in it. The composable accepts slots where you can put whatever fits your needs

See the documentation

Stephen Vinouze
  • 1,815
  • 1
  • 17
  • 28
0

You can accomplish this in many ways i guess. I will only post 2 alternatives

1- You can use Scaffold with drawerContent and adding your layout as this content

val scaffoldState = rememberScaffoldState()

val coroutineScope = rememberCoroutineScope()
val openDrawer: () -> Unit = { coroutineScope.launch { scaffoldState.drawerState.open() } }
val closeDrawer: () -> Unit = { coroutineScope.launch { scaffoldState.drawerState.close() } }


Scaffold(
    scaffoldState = scaffoldState,
    drawerContent = {
        AppDrawer(
            currentRoute = currentRoute,
            navigateToHome = {
                currentRoute = Routes.HOME_ROUTE
                navController.popBackStack()
                navController.navigate(currentRoute)
            },
            navigateToSettings = {
                currentRoute = Routes.SETTINGS_ROUTE
                navController.popBackStack()
                navController.navigate(currentRoute)
            },
            closeDrawer = closeDrawer
        )
    },

) {
    NavHost(
        navController = navController,
        startDestination = Routes.HOME_ROUTE
    ) {
        composable(Routes.HOME_ROUTE) {
            HomeComponent()
        }

        composable(Routes.SETTINGS_ROUTE) {
            SettingsComponent()
        }
    }
}

Our drawer content

@Composable
fun AppDrawer(
    currentRoute: String,
    navigateToHome: () -> Unit,
    navigateToSettings: () -> Unit,
    closeDrawer: () -> Unit
) {

    Column(modifier = Modifier.fillMaxSize()) {
        DrawerHeader()
        DrawerButton(
            icon = Icons.Filled.Home,
            label = "Home",
            isSelected = currentRoute == Routes.HOME_ROUTE,
            action = {
                if (currentRoute != Routes.HOME_ROUTE) {
                    navigateToHome()
                }
                closeDrawer()
            }
        )

        DrawerButton(
            icon = Icons.Filled.Settings,
            label = "Settings",
            isSelected = currentRoute == Routes.SETTINGS_ROUTE,
            action = {
                if (currentRoute != Routes.SETTINGS_ROUTE) {
                    navigateToSettings()
                }
                closeDrawer()
            }
        )
    }
}

You need to set scaffoldState to have drawer to be able to open or close with other interactions other than drawable behavior. openDrawer and closeDrawer lambdas are required if you need to open or close drawer like touching an item on drawer on content.

2- Using ModalDrawer

@Composable
private fun ModalDrawerComponent() {
    val drawerState = rememberDrawerState(DrawerValue.Closed)
    val coroutineScope = rememberCoroutineScope()
    val openDrawer: () -> Unit = { coroutineScope.launch { drawerState.open() } }
    val closeDrawer: () -> Unit = { coroutineScope.launch { drawerState.close() } }
    var selectedIndex by remember { mutableStateOf(0) }

    ModalDrawer(
        drawerState = drawerState,
        drawerContent = {
            ModalDrawerContentHeader()
            Divider()
            ModelDrawerContentBody(
                selectedIndex,
                onSelected = {
                    selectedIndex = it
                },
                closeDrawer = closeDrawer
            )
        },
        content = {
            Column(modifier = Modifier.fillMaxSize()) {
//                ModalDrawerTopAppBar(openDrawer)
                ModalContent(openDrawer)
            }
        }
    )
}

With ModalDrawer you set your Content as you wish if you don't want to add TopAppBar you just don't add it inside content. I commented it here to display that it's not there.

You can check repo that contains implementations here.

Thracian
  • 43,021
  • 16
  • 133
  • 222