Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
📋 Screens, Lists और Navigation  ·  Lesson 27

Navigation Drawer (Side Menu)

Navigation drawer क्या है?

Navigation drawer वह side menu है जो ☰ tap करने या किनारे से swipe करने पर बाईं ओर से आता है। इसमें header (user photo और नाम) और destinations की list होती है।

9:41▮▮ 85%☰Student Diary⋮Maths homeworkHighPhysics notesChapter 4📝Notes📚Subjects📊Progress9:41▮▮ 85%Student Diary⋮👤Hello, Riya 👋🏠Notes📦Favourites♡Subjects⚙️Progress❓Settings🚪Help & Tutorial📝Share app
बंद और खुला — final app का drawer

Building blocks

DrawerLayoutroot – पहला child = content, दूसरा = drawerCoordinatorLayout (content)Toolbar + NavHost + BottomNav + FABNavigationView (drawer, layout_gravity="start")headerLayout + menu
Order ज़रूरी है: drawer आख़िरी child है

Step 1: activity_main.xml

XML – res/layout/activity_main.xml (Student Diary)
<?xml version="1.0" encoding="utf-8"?>
<!-- DrawerLayout = the side menu slides over the main content -->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <!-- 1st child: main content -->
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize" />
        </com.google.android.material.appbar.AppBarLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <!-- Screens (fragments) are swapped here by the Navigation Component -->
            <androidx.fragment.app.FragmentContainerView
                android:id="@+id/nav_host"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                app:defaultNavHost="true"
                app:navGraph="@navigation/nav_graph" />

            <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottomNav"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:menu="@menu/bottom_nav_menu" />
        </LinearLayout>

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="96dp"
            android:contentDescription="@string/add_note"
            app:srcCompat="@drawable/ic_add" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <!-- 2nd child: the drawer itself -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

Step 2: Drawer header

XML – res/layout/nav_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="176dp"
    android:background="@color/brand"
    android:gravity="bottom"
    android:orientation="vertical"
    android:padding="16dp">

    <ImageView
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:background="@drawable/bg_circle_white"
        android:contentDescription="@string/app_name"
        android:padding="12dp"
        android:src="@drawable/ic_note"
        app:tint="@color/brand" />

    <TextView
        android:id="@+id/tvUserName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="@string/app_name"
        android:textAppearance="?attr/textAppearanceTitleMedium"
        android:textColor="@android:color/white" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/tagline"
        android:textColor="#E0FFFFFF" />
</LinearLayout>

<group android:checkableBehavior="single"> current screen highlight करता है। Title वाला sub-menu "More" section बनाता है। Destination items nav graph ids reuse करते हैं; action_share एक normal action है।

XML – res/menu/drawer_menu.xml
<?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/notesFragment" android:icon="@drawable/ic_note" android:title="@string/menu_notes" />
        <item android:id="@+id/favoritesFragment" android:icon="@drawable/ic_star" android:title="@string/menu_favourites" />
        <item android:id="@+id/subjectsFragment" android:icon="@drawable/ic_subject" android:title="@string/menu_subjects" />
        <item android:id="@+id/statsFragment" android:icon="@drawable/ic_stats" android:title="@string/menu_stats" />
    </group>
    <item android:title="@string/menu_more">
        <menu>
            <item android:id="@+id/settingsFragment" android:icon="@drawable/ic_settings" android:title="@string/menu_settings" />
            <item android:id="@+id/helpFragment" android:icon="@drawable/ic_help" android:title="@string/menu_help" />
            <item android:id="@+id/action_share" android:icon="@drawable/ic_share" android:title="@string/share_app" />
        </menu>
    </item>
</menu>

Step 4: MainActivity

Kotlin – MainActivity.kt (complete)
package com.codingeasily.studentdiary

import android.Manifest
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.codingeasily.studentdiary.data.SettingsStore
import com.codingeasily.studentdiary.databinding.ActivityMainBinding
import com.codingeasily.studentdiary.databinding.NavHeaderBinding
import com.codingeasily.studentdiary.reminder.NotificationHelper
import com.google.android.material.snackbar.Snackbar

/**
 * The only Activity. It hosts: Toolbar + Navigation Drawer + Bottom Navigation + FAB
 * and a NavHostFragment that swaps the screens (fragments).
 */
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var navController: NavController
    private lateinit var appBarConfiguration: AppBarConfiguration

    // Android 13+: ask for notification permission (result comes back here)
    private val notificationPermission =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
            if (!granted) {
                Snackbar.make(binding.root, R.string.notifications_off, Snackbar.LENGTH_LONG).show()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setSupportActionBar(binding.toolbar)

        val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment
        navController = navHost.navController

        // Top-level screens show the ☰ (drawer) icon; other screens show ←
        val topLevel = setOf(
            R.id.notesFragment, R.id.subjectsFragment, R.id.statsFragment,
            R.id.favoritesFragment, R.id.settingsFragment, R.id.helpFragment
        )
        appBarConfiguration = AppBarConfiguration(topLevel, binding.drawerLayout)
        setupActionBarWithNavController(navController, appBarConfiguration)
        binding.bottomNav.setupWithNavController(navController)
        binding.navView.setupWithNavController(navController)

        // Drawer has one extra item ("Share app") that is not a screen
        binding.navView.setNavigationItemSelectedListener { item ->
            if (item.itemId == R.id.action_share) shareApp()
            else NavigationUI.onNavDestinationSelected(item, navController)
            binding.drawerLayout.closeDrawer(GravityCompat.START)
            true
        }

        // Show bottom bar only on the 3 main tabs, FAB only on the notes list
        val bottomScreens = setOf(R.id.notesFragment, R.id.subjectsFragment, R.id.statsFragment)
        navController.addOnDestinationChangedListener { _, destination, _ ->
            binding.bottomNav.isVisible = destination.id in bottomScreens
            if (destination.id == R.id.notesFragment) binding.fab.show() else binding.fab.hide()
        }
        binding.fab.setOnClickListener { navController.navigate(R.id.action_global_editor) }

        // Close the drawer with the back button before leaving the screen
        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
                    binding.drawerLayout.closeDrawer(GravityCompat.START)
                } else {
                    isEnabled = false
                    onBackPressedDispatcher.onBackPressed()
                    isEnabled = true
                }
            }
        })

        askNotificationPermission()
    }

    override fun onResume() {
        super.onResume()
        // The name can change in Settings, so refresh the drawer header every time
        val header = NavHeaderBinding.bind(binding.navView.getHeaderView(0))
        header.tvUserName.text = getString(R.string.hello_user, SettingsStore(this).userName)
    }

    override fun onSupportNavigateUp(): Boolean =
        navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()

    private fun askNotificationPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !NotificationHelper.canNotify(this)) {
            notificationPermission.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }

    private fun shareApp() {
        val send = Intent(Intent.ACTION_SEND).apply {
            type = "text/plain"
            putExtra(Intent.EXTRA_TEXT, getString(R.string.share_text))
        }
        startActivity(Intent.createChooser(send, getString(R.string.share_app)))
    }
}

Drawer click कैसे काम करता है

UserNavigationViewMainActivityNavController"Favourites" tapitem selected listeneronNavDestinationSelected(item)favoritesFragment दिखाओcloseDrawer(START)destination बदली → item checked
Share app अलग से handle होता है (destination नहीं)

Back button से drawer बंद

MainActivity का OnBackPressedCallback isDrawerOpen(GravityCompat.START) check करता है: drawer खुला हो तो Back उसे बंद करता है; नहीं तो callback कुछ पल के लिए खुद को disable करके NavHost को पीछे जाने देता है।

आम गलतियाँ

  • DrawerLayout में NavigationView पहले रखना → content ढक जाता है और बंद नहीं होता।
  • NavigationView पर android:layout_gravity="start" नहीं → crash "No drawer view found"।
  • ActionBar वाली theme और आपका Toolbar → दो bars; NoActionBar theme use करें।
  • onNavDestinationSelected call किए बिना setNavigationItemSelectedListener → menu clicks navigate करना बंद।

सारांश

  • DrawerLayout(content, NavigationView) + header layout + menu XML।
  • AppBarConfiguration(topLevelIds, drawerLayout) ☰ icon देता है; navView.setupWithNavController items जोड़ता है।
  • Extra items खुद handle करें, drawer बंद करें, और Back पर बंद करें।
✅ Practice

Drawer में "Rate us" item जोड़िए जो implicit intent से Play Store page खोले, और header में नाम के नीचे user का email दिखाइए।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

Drawer या bottom navigation?
Bottom navigation लगातार use होने वाली 3–5 screens के लिए है। Drawer में ज़्यादा destinations और Settings, Help, Share जैसे कम use होने वाले items आते हैं। Student Diary दोनों use करती है।
Hamburger icon क्यों नहीं दिखता?
AppBarConfiguration में DrawerLayout दें और setupActionBarWithNavController call करें। Current destination top-level ids में से एक होनी चाहिए।
Code से header text कैसे बदलें?
navView.getHeaderView(0) से header लें, NavHeaderBinding.bind(...) से bind करें और TextView का text set करें।
← Android Tutorial (Kotlin)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicTabLayout और ViewPager2 आपकी प्रगति: 27 / 43 (63%) · Lesson 28 / 43 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें