How to create navigation drawer with Jetpack compose?

Last updated Sep 10, 2021


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

Jetpack Compose NavigationDrawer example

 

Jetpack Compose NavigationDrawer example
Jetpack Compose NavigationDrawer example
Jetpack Compose NavigationDrawer example

 

Conclusion: In this Jetpack Navigation Drawer we covered how to create Navigation drawer with scaffold layout and Appbar Layout


Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

36 Views

Subscribe For Daily Updates

Flutter Questions
Android Questions