In this Jetpack compose tutorial we will learn How to create navigation drawer in Android application using Jetpack Compose.
To create a navigation drawer we are going to use Scaffold. Scaffold basically provides API that will combine different material components to make our layout.
Let's get started
Step 1: Create android application in android studio
Step 2: Follow step for setup Jetpack Compose with Android Studio
Lets add simple example of Scaffold with top app bar and drawer.
@Composable fun NavigationDrawerDemo(){ Scaffold( drawerContent = { //here we are going to add drawer content which includes menu to navigate }, content = { //here we are going to show each screen layout according to menu selected }, topBar = { //here we are going to add top app bar }, ) } |
We are going to display 3 menu basically Home,Settings and Contactus
private val screens = listOf( DrawerScreens.Home, DrawerScreens.Settings, DrawerScreens.ContactUs ) |
Lets create a sealed class (where Sealed class is basically restricted class hierarchies which gives more control over inheritance)
which will contain route,title of the app bar and screen to load on selecting particular menu.
sealed class DrawerScreens( val route: String, val title: String, val screenToLoad: @Composable () -> Unit ) { object Home : DrawerScreens("home", "Home", { HomeScreen() }) object Settings : DrawerScreens("settings", "Settings", { SettingsScreen() }) object ContactUs : DrawerScreens("contactUs", "Contact Us", { ContactUsScreen() }) } |
Drawer UI
@Composable fun DrawerHeader() { Column(modifier = Modifier .fillMaxWidth() .height(200.dp) .background(Color.Blue).padding(16.dp), content = { Text("xyz@gmail.com",color = Color.White,fontSize = 20.sp) },verticalArrangement = Arrangement.Bottom) } @Composable fun Drawer( modifier: Modifier = Modifier, selectedScreen: DrawerScreens, onMenuSelected: ((drawerScreen: DrawerScreens) -> Unit)? = null ) { Column( modifier .fillMaxSize() ) { DrawerHeader() screens.forEach { screen -> Row( content = { Text( text = screen.title, fontSize = 16.sp, fontWeight = FontWeight.Bold, color = if (screen.route == selectedScreen.route) Color.White else Color.Black ) }, modifier = Modifier .padding(horizontal = 16.dp, vertical = 8.dp) .background( color = if (screen.route == selectedScreen.route) Color.Blue else Color.White, shape = RoundedCornerShape(4.dp) ) .fillMaxWidth() .clickable(onClick = { onMenuSelected?.invoke(screen) }) .padding(vertical = 8.dp, horizontal = 16.dp) ) } } }
|
Here we are going to pass currently selected menu details as well as pass a function "onMenuSelected" which will be invoked when user select any menu and according to that screen will be displayed
Let's create our 3 screens
@Composable fun HomeScreen() { Column( content = { Text(text = "You are in Home Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } @Composable fun ContactUsScreen() { Column( content = { Text(text = "You are in Contact Us Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } @Composable fun SettingsScreen() { Column( content = { Text(text = "You are in Settings Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } |
Create Appbar with jetpack compose
The top appbar displays some information with actions related to the current screen.
It takes title,navigation icon,actions,background color etc as a parameters
@Composable fun TopAppBarLayout( currentScreen: DrawerScreens, scope: CoroutineScope, scaffoldState: ScaffoldState ) { TopAppBar(title = { Text(currentScreen.title) }, navigationIcon = { IconButton(onClick = { scope.launch { scaffoldState.drawerState.open() } }) { Icon(Icons.Filled.Menu, "") } }, backgroundColor = Color.Blue, contentColor = Color.White) } |
Connect Drawer and Appbar together
To connect appbar and drawer with below code
@Composable fun NavigationDrawer() { val scaffoldState = rememberScaffoldState() val scope = rememberCoroutineScope() val currentScreen = remember { mutableStateOf(DrawerScreens.Home) } Scaffold( scaffoldState = scaffoldState, drawerContent = { Drawer( selectedScreen = currentScreen.value, onMenuSelected = { drawerScreen: DrawerScreens -> scope.launch { scaffoldState.drawerState.close() } currentScreen.value = drawerScreen }) }, content = { currentScreen.value.screenToLoad() }, topBar = { TopAppBarLayout(currentScreen.value, scope, scaffoldState) }, ) } |
Full source code for Navigation drawer with Jetpack compose
package com.example.jetpack import android.os.Bundle import android.view.WindowManager import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.example.jetpack.ui.theme.JetPackTheme import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) setContent { MaterialTheme { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { NavigationDrawer() } } } } } @Composable fun NavigationDrawer() { val scaffoldState = rememberScaffoldState() val scope = rememberCoroutineScope() val currentScreen = remember { mutableStateOf(DrawerScreens.Home) } Scaffold( scaffoldState = scaffoldState, drawerContent = { Drawer( selectedScreen = currentScreen.value, onMenuSelected = { drawerScreen: DrawerScreens -> scope.launch { scaffoldState.drawerState.close() } currentScreen.value = drawerScreen }) }, content = { currentScreen.value.screenToLoad() }, topBar = { TopAppBarLayout(currentScreen.value, scope, scaffoldState) }, ) } @Composable fun TopAppBarLayout( currentScreen: DrawerScreens, scope: CoroutineScope, scaffoldState: ScaffoldState ) { TopAppBar(title = { Text(currentScreen.title) }, navigationIcon = { IconButton(onClick = { scope.launch { scaffoldState.drawerState.open() } }) { Icon(Icons.Filled.Menu, "") } }, backgroundColor = Color.Blue, contentColor = Color.White) } @Preview(showBackground = true) @Composable fun DefaultPreview() { JetPackTheme { NavigationDrawer() } } private val screens = listOf( DrawerScreens.Home, DrawerScreens.Settings, DrawerScreens.ContactUs ) @Composable fun DrawerHeader() { Column(modifier = Modifier .fillMaxWidth() .height(200.dp) .background(Color.Blue).padding(16.dp), content = { Text("xyz@gmail.com",color = Color.White,fontSize = 20.sp) },verticalArrangement = Arrangement.Bottom) } @Composable fun Drawer( modifier: Modifier = Modifier, selectedScreen: DrawerScreens, onMenuSelected: ((drawerScreen: DrawerScreens) -> Unit)? = null ) { Column( modifier .fillMaxSize() ) { DrawerHeader() screens.forEach { screen -> Row( content = { Text( text = screen.title, fontSize = 16.sp, fontWeight = FontWeight.Bold, color = if (screen.route == selectedScreen.route) Color.White else Color.Black ) }, modifier = Modifier .padding(horizontal = 16.dp, vertical = 8.dp) .background( color = if (screen.route == selectedScreen.route) Color.Blue else Color.White, shape = RoundedCornerShape(4.dp) ) .fillMaxWidth() .clickable(onClick = { onMenuSelected?.invoke(screen) }) .padding(vertical = 8.dp, horizontal = 16.dp) ) } } } sealed class DrawerScreens( val route: String, val title: String, val screenToLoad: @Composable () -> Unit ) { object Home : DrawerScreens("home", "Home", { HomeScreen() }) object Settings : DrawerScreens("settings", "Settings", { SettingsScreen() }) object ContactUs : DrawerScreens("contactUs", "Contact Us", { ContactUsScreen() }) } @Composable fun HomeScreen() { Column( content = { Text(text = "You are in Home Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } @Composable fun ContactUsScreen() { Column( content = { Text(text = "You are in Contact Us Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } @Composable fun SettingsScreen() { Column( content = { Text(text = "You are in Settings Screen") }, modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) } |
Images
Conclusion: In this Jetpack Navigation Drawer we covered how to create Navigation drawer with scaffold layout and Appbar Layout
Article Contributed By :
|
|
|
|
2974 Views |