How to use Navigation component with DrawerLayout in Android

Issue #349

Screenshot_1565169686

build.gradle

1
2
3
dependencies {
classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha05'
}

app/build.gradle

1
2
3
4
5
6
7
8
9
10
apply plugin: 'androidx.navigation.safeargs'

dependencies {
def navigationVersion = "2.0.0"
def drawerLayoutVersion = "1.0.0"

implementation "androidx.drawerlayout:drawerlayout:$drawerLayoutVersion"
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
}

main_activity.xml

  • Use CoordinatorLayout and ToolBar
  • Define layout_gravity for NavigationView
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
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"
tools:context=".MainActivity">

<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">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar"/>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/hostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_graph"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/navigationView"
android:fitsSystemWindows="true"
android:layout_gravity="start"
app:menu="@menu/drawer_menu"/>
</androidx.drawerlayout.widget.DrawerLayout>

navigation/navigation_graph.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigationGraph"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/aboutFragment">
<fragment
android:id="@+id/aboutFragment"
android:name="com.onmyway133.whatsupintech.AboutFragment"
android:label="@string/menu_about"
tools:layout="@layout/about_fragment" />
<fragment
android:id="@+id/feedFragment"
android:name="com.onmyway133.whatsupintech.FeedFragment"
android:label="@string/menu_git_hub"
tools:layout="@layout/feed_fragment" />
<fragment
android:id="@+id/webFragment"
android:name="com.onmyway133.whatsupintech.WebFragment"
tools:layout="@layout/web_fragment"/>
</navigation>

menu/drawer_menu.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<group android:checkableBehavior="single">
<item
android:id="@+id/about"
android:title="@string/menu_about" />
<item
android:id="@+id/hackerNews"
android:title="@string/menu_hacker_news" />
<item
android:id="@+id/reddit"
android:title="@string/menu_reddit" />
<item
android:id="@+id/dev"
android:title="@string/menu_dev" />
<item
android:id="@+id/gitHub"
android:title="@string/menu_git_hub" />
</group>
</menu>

MainActivity.kotlin

  • Use AppBarConfiguration to define multiple top level destinations
  • Convert Toolbar to ActionBar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.onmyway133.whatsupintech

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.GravityCompat
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import kotlinx.android.synthetic.main.main_activity.*

class MainActivity : AppCompatActivity() {

lateinit var appBarConfig: AppBarConfiguration

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
setupNavigationController()
}

fun setupNavigationController() {
val navigationController = findNavController(R.id.hostFragment)

setSupportActionBar(toolbar)

appBarConfig = AppBarConfiguration(setOf(R.id.aboutFragment, R.id.feedFragment), drawerLayout)
setupActionBarWithNavController(navigationController, appBarConfig)
navigationView.setupWithNavController(navigationController)
navigationView.setNavigationItemSelectedListener { menuItem ->
drawerLayout.closeDrawers()
menuItem.isChecked = true
when (menuItem.itemId) {
R.id.about -> navigationController.navigate(R.id.aboutFragment)
R.id.gitHub, R.id.reddit, R.id.hackerNews, R.id.dev -> navigationController.navigate(R.id.feedFragment)
}

true
}
}

override fun onSupportNavigateUp(): Boolean {
val navigationController = findNavController(R.id.hostFragment)
return navigationController.navigateUp(appBarConfig) || super.onSupportNavigateUp()
}

override fun onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START)
} else {
return super.onBackPressed()
}
}
}

Update UI components with NavigationUI

Tie destinations to menu items

NavigationUI also provides helpers for tying destinations to menu-driven UI components. NavigationUI contains a helper method, onNavDestinationSelected(), which takes a MenuItem along with the NavController that hosts the associated destination. If the id of the MenuItem matches the id of the destination, the NavController can then navigate to that destination.

Add a navigation drawer

The drawer icon is displayed on all top-level destinations that use a DrawerLayout. Top-level destinations are the root-level destinations of your app. They do not display an Up button in the app bar.

Read more

Comments