Create a Navigation Drawer

Ref: Guide: Developer.Android.Com

Initial Steps

  1. Start a new project in Android Studio
  2. Provide the appication name as you wish. Company Domain: for example smredlabs.com.
  3. Check Include Kotlin Support
  4. Click Next and select Empty Activity
  5. Click Finish after providing the activity name
For detailed steps refer: Create New Project

Add dependencies

Open build.gradle file and make sure that you have the following dependencies included

dependencies {
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
}

Add a drawer to your layout

Open activity_main.xml (Text which displays XML). Replace entire content with the code below.

<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true" />

</android.support.v4.widget.DrawerLayout>

Declare the menu items for the nav drawer

Create the menu resource at res/menu/drawer_view.xml and copy the code below

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:title="@string/drawer_home" />
        <item
            android:id="@+id/nav_about"
            android:title="@string/drawer_about" />
        <item
            android:id="@+id/nav_contact"
            android:title="@string/drawer_contact" />
        <item
            android:id="@+id/nav_credit"
            android:title="@string/drawer_credit" />
    </group>
</menu>
Define the string values in res/values/strings.xml

<resources>
    <string name="app_name">App Name</string>
    <string name="drawer_home">Home</string>
    <string name="drawer_about">About</string>
    <string name="drawer_contact">Contact</string>
    <string name="drawer_credit">Credits</string>
</resources>

To configure menu items in the drawer add the app:menu attribute in activity_main.xml (NavigationView) as shown below

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/drawer_view" />

At this point, you already have a working navigation drawer—the DrawerLayout provides built-in support for users to open and close the navigation drawer with a swipe on the side of the screen. Run the application and verify it.

Handle navigation click events

To receive callbacks when the user taps a list item in the drawer implement as shown below in MainActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

//confirm that the below has been imported
import android.support.design.widget.NavigationView
import android.support.v4.widget.DrawerLayout

class MainActivity : AppCompatActivity() {

    private lateinit var mDrawerLayout: DrawerLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // change starts here - Handle navigation click events
        mDrawerLayout = findViewById(R.id.drawer_layout)

        val navigationView: NavigationView = findViewById(R.id.nav_view)
        navigationView.setNavigationItemSelectedListener { menuItem ->
            // set item as selected to persist highlight
            menuItem.isChecked = true
            // close drawer when item is tapped
            mDrawerLayout.closeDrawers()

            // Add code here to update the UI based on the item selected
            // For example, swap UI fragments here
            when (menuItem.itemId) {
                R.id.nav_about -> {
                    //to do code
                }
                R.id.nav_contact -> {
                    //to do code
                }
            }

            true
        }
    }

}

At this point, you can run the application and verify whether the menu gets closed when you click a menu item.

Add the nav drawer button to the app bar

if your UI design includes an app bar, you should also allow users to open and close the drawer by touching the drawer icon on the top left of the app bar as shown in the figure.

Add the toolbar to your layout (activity_main.xml)

<android.support.v4.widget.DrawerLayout ...>

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

</FrameLayout>
...

</android.support.v4.widget.DrawerLayout>

Then open your manifest file (app/manifest/AndroidManifest.xml) and set the app theme to one without the action bar, such as Theme.AppCompat.Light.NoActionBar

<manifest ...>
<application
    ...
    android:theme="@style/Theme.AppCompat.Light.NoActionBar" >
...
</manifest>

if you encounter that your manifest shows android:theme="@style/AppTheme", then open "values/styles.xml" and make changes

<resources>
    ...
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        ...
    </style>
</resources>


Now the toolbar appears in the layout but it's not functioning as the app bar. To apply the toolbar as the app bar, first make sure your activity extends from AppCompatActivity. Then call setSupportActionBar() and pass the Toolbar object from your layout. Change the below in MainActivity.kt


...
import android.support.v7.app.ActionBar
import android.support.v7.widget.Toolbar
...
class MainActivity : AppCompatActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ...

        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)
        val actionbar: ActionBar? = supportActionBar
        actionbar?.apply {
            setDisplayHomeAsUpEnabled(true)
            setHomeAsUpIndicator(R.drawable.icon_menu)
        }

        ...
    }
}

Download menu icon from Material Design Icon Page (https://material.io/icons/) and rename it as icon_menu.png and copy it to res/drawable folder. Open the drawer when the button is tapped


...
import android.support.v4.view.GravityCompat
import android.view.MenuItem
...
class MainActivity : AppCompatActivity() {

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            android.R.id.home -> {
                mDrawerLayout.openDrawer(GravityCompat.START)
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}

Run and check the output

Optional - Add a header to the nav drawer

First create a new layout named nav_header.xml in res/layout. And paste the code below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="My header title"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

</LinearLayout>

Add the following app:headerLayout="@layout/nav_header" in NavigationView (activity_main.xml)

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    ...
    app:headerLayout="@layout/nav_header" />

Run and check the output

Optional - Listen for open/close events and other state changes

If your app needs to respond when the navigation drawer opens, closes, or simply changes its state and position implement the following callback methods

class MainActivity : AppCompatActivity() {

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mDrawerLayout = findViewById(R.id.drawer_layout)
        ...

        mDrawerLayout.addDrawerListener(
                object : DrawerLayout.DrawerListener {
                    override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
                        // Respond when the drawer's position changes
                    }

                    override fun onDrawerOpened(drawerView: View) {
                        // Respond when the drawer is opened
                    }

                    override fun onDrawerClosed(drawerView: View) {
                        // Respond when the drawer is closed
                    }

                    override fun onDrawerStateChanged(newState: Int) {
                        // Respond when the drawer motion state changes
                    }
                }
        )
    }
    ...
}


Email your queries to solutiomagister@gmail.com