As you probably remember, in our mockup we have presented that there will be links to filtered data (Notes and Todos). We will filter these by using the navigation drawer. Every modern application uses a navigation drawer. It's a piece of the UI that displays the application's navigation options. To define the drawer, we have to put the DrawerLayout view in our layout. Open activity_main and apply the following modification:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android=
"http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/colorPrimary" android:elevation="4dp" /> <android.support.v4.view.ViewPager xmlns:android=
"http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="@android:color/darker_gray" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="1dp" /> </android.support.v4.widget.DrawerLayout>
The main content of the screen must be the first child of DrawerLayout. The navigation drawer uses the second child as the content of the drawer. In our case, it's ListView. To tell the navigation drawer if navigation should be positioned left or right, use the layout_gravity attribute. If we plan to use the navigation drawer positioned to the right, we should set the attribute value to end.
Now we have an empty navigation drawer, and we have to populate it with some buttons. Create a new layout file for each navigation item. Call it adapter_navigation_drawer. Define it as a simple linear layout with only one button inside:
<?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="match_parent" android:orientation="vertical"> <Button android:id="@+id/drawer_item" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
Then, create a new package called navigation. In this package, create a new Kotlin data class, like this:
package com.journaler.navigation data class NavigationDrawerItem( val title: String, val onClick: Runnable )
We defined a drawer item entity. Now create one more class:
class NavigationDrawerAdapter( val ctx: Context, val items: List<NavigationDrawerItem> ) : BaseAdapter() { override fun getView(position: Int, v: View?, group: ViewGroup?):
View { val inflater = LayoutInflater.from(ctx) var view = v if (view == null) { view = inflater.inflate( R.layout.adapter_navigation_drawer, null ) as LinearLayout } val item = items[position] val title = view.findViewById<Button>(R.id.drawer_item) title.text = item.title title.setOnClickListener { item.onClick.run() } return view } override fun getItem(position: Int): Any { return items[position] } override fun getItemId(position: Int): Long { return 0L } override fun getCount(): Int { return items.size } }
This class shown here extends Android's BaseAdapter and overrides methods needed for the adapter to provide view instances. All views that the adapter creates will be assigned to expand ListView in our navigation drawer.
Finally, we will assign this adapter. To do that, we need to update our MainActivity class by executing the following piece of code:
class MainActivity : BaseActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) pager.adapter = ViewPagerAdapter(supportFragmentManager) val menuItems = mutableListOf<NavigationDrawerItem>() val today = NavigationDrawerItem( getString(R.string.today), Runnable { pager.setCurrentItem(0, true) } ) val next7Days = NavigationDrawerItem( getString(R.string.next_seven_days), Runnable { pager.setCurrentItem(1, true) } ) val todos = NavigationDrawerItem( getString(R.string.todos), Runnable { pager.setCurrentItem(2, true) } ) val notes = NavigationDrawerItem( getString(R.string.notes), Runnable { pager.setCurrentItem(3, true) } ) menuItems.add(today) menuItems.add(next7Days) menuItems.add(todos) menuItems.add(notes) val navgationDraweAdapter =
NavigationDrawerAdapter(this, menuItems) left_drawer.adapter = navgationDraweAdapter } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.drawing_menu -> { drawer_layout.openDrawer(GravityCompat.START) return true } R.id.options_menu -> { Log.v(tag, "Options menu.") return true } else -> return super.onOptionsItemSelected(item) } } }
In this code example, we instantiated several NavigationDrawerItem instances, then, we assigned a title to the buttons and Runnable actions that we will execute. Each Runnable will jump to a specific page of our view pager. We passed all instances to the adapter as one single mutable list. You may have also noticed that we changed the line for the drawing_menu item. By clicking on it, we will expand our navigation drawer. Please follow these steps:
- Build your application and run it.
- Click on the menu button at the top-right position of the main screen or expand the navigation drawer by swiping from the far-left side of the screen to the right.
- Click on buttons.
- You will notice that the view pager is animating its page positions below the navigation drawer.
![](assets/ec3eed2d-ebf3-4377-90f5-f07682c6b54e.png)