Convert NavigationView to Fragment (1/2)

- Replace NavigationView with DrawerFragment
- Load groups and filters in DrawerFragment, rather than in
  PeopleActivity directly
- based on RecylcerView, which seems more future-proof
- LTR layout and A11Y is handled
- new badge is implemented
- menu selection is implemented

Bug: 34062530

Test: quick sanity check

Change-Id: I630978e64dc4fd386e25cedfd04f53ea2bd8679f
diff --git a/res/drawable/drawer_item_background.xml b/res/drawable/drawer_item_background.xml
index 88f6690..dc8a9f2 100644
--- a/res/drawable/drawer_item_background.xml
+++ b/res/drawable/drawer_item_background.xml
@@ -14,12 +14,9 @@
      limitations under the License.
 -->
 
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/nav_item_selected_background">
-  <item>
-    <selector>
-      <item android:drawable="@color/nav_item_selected_background" android:state_checked="true"/>
-      <item android:drawable="@android:color/transparent"/>
-    </selector>
-  </item>
-</ripple>
\ No newline at end of file
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_activated="true"
+        android:drawable="@color/drawer_selected_color"/>
+  <item android:drawable="@drawable/ripple_background" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/ripple_background.xml b/res/drawable/ripple_background.xml
new file mode 100644
index 0000000..574dff1
--- /dev/null
+++ b/res/drawable/ripple_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/control_highlight_color" />
\ No newline at end of file
diff --git a/res/layout/assistant_new_badge.xml b/res/layout/assistant_new_badge.xml
deleted file mode 100644
index 21b5297..0000000
--- a/res/layout/assistant_new_badge.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/assistant_new_badge"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_vertical"
-    android:paddingLeft="@dimen/nav_new_badge_horizontal_pad"
-    android:paddingTop="@dimen/nav_new_badge_vertical_pad"
-    android:paddingRight="@dimen/nav_new_badge_horizontal_pad"
-    android:paddingBottom="@dimen/nav_new_badge_vertical_pad"
-    android:background="@drawable/new_badge_background"
-    android:textSize="@dimen/nav_new_badge_font_size"
-    android:textStyle="bold"
-    android:textAllCaps="true"
-    android:textColor="@android:color/white"
-    android:text="@string/menu_assistant_new_badge"/>
\ No newline at end of file
diff --git a/res/layout/contacts_drawer_activity.xml b/res/layout/contacts_drawer_activity.xml
index 0e77058..5b21a31 100644
--- a/res/layout/contacts_drawer_activity.xml
+++ b/res/layout/contacts_drawer_activity.xml
@@ -17,7 +17,6 @@
 
 <android.support.v4.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/drawer_layout"
     android:layout_width="match_parent"
@@ -42,15 +41,11 @@
             android:background="?android:attr/windowBackground" />
     </LinearLayout>
 
-    <android.support.design.widget.NavigationView
-        android:id="@+id/nav_view"
-        android:theme="@style/NavigationDrawerMenuItemTextAppearance"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+    <fragment
+        android:id="@+id/drawer"
+        android:name="com.android.contacts.drawer.DrawerFragment"
         android:layout_gravity="start"
-        android:fitsSystemWindows="true"
-        app:itemBackground="@drawable/drawer_item_background"
-        app:headerLayout="@layout/nav_header_main"
-        app:menu="@menu/activity_main_drawer"/>
+        android:layout_width="@dimen/drawer_width"
+        android:layout_height="match_parent" />
 
 </android.support.v4.widget.DrawerLayout>
\ No newline at end of file
diff --git a/res/layout/drawer_fragment.xml b/res/layout/drawer_fragment.xml
new file mode 100644
index 0000000..ea9eed0
--- /dev/null
+++ b/res/layout/drawer_fragment.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true">
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/list"
+        android:background="#FAFAFA"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:divider="@null" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/drawer_header.xml b/res/layout/drawer_header.xml
new file mode 100644
index 0000000..1f0151b
--- /dev/null
+++ b/res/layout/drawer_header.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/label_header"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical"
+    android:orientation="vertical"
+    android:background="@color/navigation_drawer_background_color">
+
+    <include layout="@layout/drawer_horizontal_divider" />
+
+    <FrameLayout
+        style="@style/DrawerHeaderItemStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:clickable="false">
+
+        <TextView
+            android:id="@+id/title"
+            style="@style/DrawerHeaderTextStyle"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"/>
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/drawer_horizontal_divider.xml b/res/layout/drawer_horizontal_divider.xml
new file mode 100644
index 0000000..ca096fa
--- /dev/null
+++ b/res/layout/drawer_horizontal_divider.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="16dp"
+    android:importantForAccessibility="no">
+
+    <View
+        android:id="@+id/divider_top"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:layout_gravity="center_vertical"
+        android:background="@color/drawer_divider_color"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/drawer_item.xml b/res/layout/drawer_item.xml
new file mode 100644
index 0000000..f7621a3
--- /dev/null
+++ b/res/layout/drawer_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/DrawerItemStyle">
+
+    <ImageView
+        android:id="@+id/icon"
+        style="@style/DrawerItemIconStyle"/>
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/DrawerItemTextStyle" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/drawer_primary_item.xml b/res/layout/drawer_primary_item.xml
new file mode 100644
index 0000000..cc7bf26
--- /dev/null
+++ b/res/layout/drawer_primary_item.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/DrawerPrimaryItemStyle">
+
+    <ImageView
+        android:id="@+id/icon"
+        style="@style/DrawerItemIconStyle"/>
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/DrawerItemTextStyle" />
+
+    <TextView
+        android:id="@+id/assistant_new_badge"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical|end"
+        android:paddingLeft="@dimen/nav_new_badge_horizontal_pad"
+        android:paddingTop="@dimen/nav_new_badge_vertical_pad"
+        android:paddingRight="@dimen/nav_new_badge_horizontal_pad"
+        android:paddingBottom="@dimen/nav_new_badge_vertical_pad"
+        android:background="@drawable/new_badge_background"
+        android:textSize="@dimen/nav_new_badge_font_size"
+        android:textStyle="bold"
+        android:textAllCaps="true"
+        android:textColor="@android:color/white"
+        android:text="@string/menu_assistant_new_badge"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/nav_drawer_spacer b/res/layout/nav_drawer_spacer
new file mode 100644
index 0000000..45ecfc4
--- /dev/null
+++ b/res/layout/nav_drawer_spacer
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+      android:id="@+id/nav_drawer_spacer"
+      android:layout_width="match_parent"
+      android:layout_height="@dimen/nav_drawer_spacer_height"
+      android:background="@drawable/drawer_item_background"
+      android:importantForAccessibility="no"/>
\ No newline at end of file
diff --git a/res/menu/activity_main_drawer.xml b/res/menu/activity_main_drawer.xml
deleted file mode 100644
index 07e9802..0000000
--- a/res/menu/activity_main_drawer.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright (C) 2016 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-
-    <group android:id="@+id/nav_utilities">
-        <item
-            android:id="@+id/nav_all_contacts"
-            android:icon="@drawable/quantum_ic_account_circle_vd_theme_24"
-            android:title="@string/contactsList" />
-        <item
-            android:id="@+id/nav_assistant"
-            app:actionViewClass="android.widget.LinearLayout"
-            android:icon="@drawable/quantum_ic_assistant_vd_theme_24"
-            android:title="@string/menu_assistant"/>
-    </group>
-
-    <group android:id="@+id/groups">
-        <item
-            android:id="@+id/nav_groups"
-            android:title="@string/menu_title_groups">
-            <menu/>
-        </item>
-    </group>
-
-    <group android:id="@+id/filters">
-        <item
-            android:id="@+id/nav_filters"
-            android:title="@string/menu_title_filters">
-            <menu/>
-        </item>
-    </group>
-
-    <group android:id="@+id/nav_misc">
-        <item
-            android:id="@+id/nav_settings"
-            android:icon="@drawable/quantum_ic_settings_vd_theme_24"
-            android:title="@string/menu_settings"/>
-        <item
-            android:id="@+id/nav_help"
-            android:icon="@drawable/quantum_ic_help_vd_theme_24"
-            android:title="@string/menu_help"/>
-    </group>
-
-</menu>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 48f34f2..7753d7d 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -59,4 +59,7 @@
     <dimen name="floating_action_button_margin_right">32dp</dimen>
     <!-- Bottom margin of the floating action button -->
     <dimen name="floating_action_button_margin_bottom">32dp</dimen>
+
+    <!-- Side padding within the navigation drawer -->
+    <dimen name="drawer_side_padding">24dp</dimen>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index d5f2da3..e89ed9f 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -241,4 +241,17 @@
 
     <!-- Background color for sync-off alert. -->
     <color name="alert_background">#e0e0e0</color>
+
+    <!-- Divider color in navigation drawer -->
+    <color name="drawer_divider_color">#E5E5E5</color>
+
+    <!-- Background color for the navigation drawer -->
+    <color name="navigation_drawer_background_color">#FAFAFA</color>
+
+    <!-- Background color for the current selected item in the navigation drawer -->
+    <color name="drawer_selected_color">#E8E8E8</color>
+
+    <!-- Highlight color used in places such as ripples -->
+    <color name="control_highlight_color">#1A000000</color>
+
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b33975f..2c47f39 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -364,4 +364,19 @@
     <!-- Row padding for call subject history items. -->
     <dimen name="call_subject_history_item_padding">15dp</dimen>
 
+    <!-- The width of the drawer -->
+    <dimen name="drawer_width">320dp</dimen>
+    <!-- Minimum height of items in navigation drawer -->
+    <dimen name="drawer_item_fixed_height">48dp</dimen>
+    <!-- Side padding within the navigation drawer -->
+    <dimen name="drawer_side_padding">16dp</dimen>
+    <!-- Size of the icon in navigation drawer -->
+    <dimen name="drawer_item_icon_size">32dp</dimen>
+    <!-- The side margin of the item text in navigation drawer -->
+    <dimen name="drawer_item_text_margin">32dp</dimen>
+    <!-- The height of the spacer in navigation drawer -->
+    <dimen name="nav_drawer_spacer_height">8dp</dimen>
+    <!-- Side padding within the navigation drawer -->
+    <dimen name="drawer_label_header_end_padding">24dp</dimen>
+
 </resources>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 0808496..a4b8b4b 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -47,11 +47,32 @@
     <!-- Menu group ID for settings and help & feedback  -->
     <item type="id" name="nav_misc" />
 
-    <!-- Menu group ID for the contact groups -->
-    <item type="id" name="nav_groups_items" />
+    <!-- Menu ID for Contacts menu -->
+    <item type="id" name="nav_all_contacts" />
 
-    <!-- Menu group ID for the contact filters -->
-    <item type="id" name="nav_filters_items" />
+    <!-- Menu ID for Suggestions menu -->
+    <item type="id" name="nav_assistant" />
+
+    <!-- Menu ID for group header -->
+    <item type="id" name="nav_groups" />
+
+    <!-- Menu ID for each group menu item -->
+    <item type="id" name="nav_group" />
+
+    <!-- Menu ID for create label menu item -->
+    <item type="id" name="nav_create_label" />
+
+    <!-- Menu ID for filter header -->
+    <item type="id" name="nav_filters" />
+
+    <!-- Menu ID for each filter menu item -->
+    <item type="id" name="nav_filter" />
+
+    <!-- Menu ID for Settings menu -->
+    <item type="id" name="nav_settings" />
+
+    <!-- Menu ID for help & feedback  menu -->
+    <item type="id" name="nav_help" />
 
     <!-- For vcard.ImportVCardActivity -->
     <item type="id" name="dialog_cache_vcard"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 053d0e3..488a1db 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -709,6 +709,9 @@
     <!-- Close drawer content descriptions [CHAR LIMIT=40] -->
     <string name="navigation_drawer_close">Close navigation drawer</string>
 
+    <!-- Content description of label name in navigation drawer. For example: Coworker Label, Friends Label [CHAR LIMIT=30] -->
+    <string name="navigation_drawer_label"><xliff:g id="label_name">%s</xliff:g> label</string>
+
     <!-- Menu section title of "labels" [CHAR LIMIT=20] -->
     <string name="menu_title_groups">Labels</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a1875ca..50971b0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -13,7 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+           xmlns:tools="http://schemas.android.com/tools">
 
     <style name="EditorActivityTheme" parent="@style/PeopleActivityTheme">
         <item name="actionBarStyle">@style/EditorActionBarStyle</item>
@@ -515,4 +516,74 @@
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:statusBarColor">@color/contextual_selection_bar_status_bar_color</item>
     </style>
+
+    <!-- Style for item in navigation drawer -->
+    <style name="DrawerItemStyle">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">@dimen/drawer_item_fixed_height</item>
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:background">@drawable/drawer_item_background</item>
+        <item name="android:orientation">horizontal</item>
+        <item name="android:paddingStart">@dimen/drawer_side_padding</item>
+    </style>
+
+    <style name="DrawerPrimaryItemStyle" parent="DrawerItemStyle">
+        <item name="android:paddingEnd">@dimen/drawer_item_text_margin</item>
+    </style>
+
+    <!-- Style for item icon in navigation drawer -->
+    <style name="DrawerItemIconStyle">
+        <item name="android:layout_width">@dimen/drawer_item_icon_size</item>
+        <item name="android:layout_height">@dimen/drawer_item_icon_size</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center</item>
+        <item name="android:scaleType">center</item>
+    </style>
+
+    <!-- Style for primary item text in navigation drawer -->
+    <style name="DrawerItemTextStyle" parent="DrawerTextStyle">
+        <item name="android:textColor">@color/primary_text_color</item>
+        <item name="android:layout_width">0dip</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_weight">1</item>
+        <item name="android:layout_marginStart">@dimen/drawer_item_text_margin</item>
+        <item name="android:layout_marginEnd">@dimen/drawer_item_text_margin</item>
+    </style>
+
+    <style name="DrawerTextStyle">
+        <item name="android:fontFamily" tools:ignore="NewApi">sans-serif-medium</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="DrawerItemTextActiveStyle">
+        <item name="android:textColor">@color/primary_color</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+
+    <style name="DrawerItemTextInactiveStyle">
+        <item name="android:textColor">@color/quantum_black_text</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+
+    <style name="DrawerHeaderTextStyle" parent="DrawerTextStyle">
+        <item name="android:layout_gravity">center_vertical|start</item>
+        <item name="android:paddingTop">12dp</item>
+        <item name="android:paddingBottom">12dp</item>
+        <item name="android:textColor">@color/quantum_black_secondary_text</item>
+        <item name="android:textSize">14sp</item>
+    </style>
+
+    <style name="DrawerBadgeStyle" parent="DrawerHeaderTextStyle">
+        <item name="android:layout_gravity">center_vertical|end</item>
+    </style>
+
+    <style name="DrawerHeaderItemStyle">
+        <item name="android:paddingStart">@dimen/drawer_side_padding</item>
+        <item name="android:paddingEnd">@dimen/drawer_label_header_end_padding</item>
+    </style>
+
 </resources>
diff --git a/src-bind/com/android/contactsbind/ObjectFactory.java b/src-bind/com/android/contactsbind/ObjectFactory.java
index 41e9df4..c5170be 100644
--- a/src-bind/com/android/contactsbind/ObjectFactory.java
+++ b/src-bind/com/android/contactsbind/ObjectFactory.java
@@ -46,4 +46,8 @@
     public static Intent getContactSheetIntent(Context context, Uri contactLookupUri) {
         return null;
     }
+
+    public static Uri getWelcomeUri() {
+        return null;
+    }
 }
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index d2157ea..4a222ad 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -29,7 +29,6 @@
 import android.content.SyncStatusObserver;
 import android.content.res.Configuration;
 import android.graphics.Color;
-import android.graphics.PorterDuff;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -37,51 +36,39 @@
 import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.ProviderStatus;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
 import android.support.design.widget.CoordinatorLayout;
-import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.LocalBroadcastManager;
 import android.support.v4.view.GravityCompat;
-import android.support.v4.view.MenuItemCompat;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;
-import android.view.Gravity;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import com.android.contacts.AppCompatContactsActivity;
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
 import com.android.contacts.compat.CompatUtils;
+import com.android.contacts.drawer.DrawerFragment;
+import com.android.contacts.drawer.DrawerFragment.DrawerFragmentListener;
 import com.android.contacts.editor.ContactEditorFragment;
 import com.android.contacts.editor.SelectAccountDialogFragment;
 import com.android.contacts.group.GroupListItem;
 import com.android.contacts.group.GroupMembersFragment;
-import com.android.contacts.group.GroupMetaData;
 import com.android.contacts.group.GroupNameEditDialogFragment;
 import com.android.contacts.group.GroupUtil;
-import com.android.contacts.group.GroupsFragment;
-import com.android.contacts.group.GroupsFragment.GroupsListener;
-import com.android.contacts.interactions.AccountFiltersFragment;
-import com.android.contacts.interactions.AccountFiltersFragment.AccountFiltersListener;
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.list.AccountFilterActivity;
 import com.android.contacts.list.ContactListFilter;
@@ -97,8 +84,6 @@
 import com.android.contacts.logging.Logger;
 import com.android.contacts.logging.ScreenEvent.ScreenType;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.account.AccountDisplayInfo;
-import com.android.contacts.model.account.AccountDisplayInfoFactory;
 import com.android.contacts.model.account.AccountInfo;
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferenceActivity;
@@ -116,19 +101,14 @@
 import com.google.common.util.concurrent.Futures;
 
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Displays a list to browse contacts.
  */
 public class PeopleActivity extends AppCompatContactsActivity implements
-        AccountFiltersListener,
-        GroupsListener,
-        NavigationView.OnNavigationItemSelectedListener,
+        DrawerFragmentListener,
         SelectAccountDialogFragment.Listener {
 
     /** Possible views of Contacts app. */
@@ -144,8 +124,6 @@
     private static final String TAG_ALL = "contacts-all";
     private static final String TAG_UNAVAILABLE = "contacts-unavailable";
     private static final String TAG_GROUP_VIEW = "contacts-groups";
-    private static final String TAG_GROUPS = "groups";
-    private static final String TAG_FILTERS = "filters";
     private static final String TAG_SELECT_ACCOUNT_DIALOG = "selectAccountDialog";
     private static final String TAG_GROUP_NAME_EDIT_DIALOG = "groupNameEditDialog";
 
@@ -199,26 +177,17 @@
     private final int mInstanceId;
     private static final AtomicInteger sNextInstanceId = new AtomicInteger();
 
-    /** Navigation drawer related */
     private ContactListFilterController mContactListFilterController;
+
+    /** Navigation drawer related */
     private DrawerLayout mDrawerLayout;
+    private DrawerFragment mDrawerFragment;
     private ContactsActionBarDrawerToggle mToggle;
     private Toolbar mToolbar;
-    private NavigationView mNavigationView;
 
     // The account the new group will be created under.
     private AccountWithDataSet mNewGroupAccount;
 
-    // Recycle badge if possible
-    private TextView mAssistantNewBadge;
-
-    // Checkable menu item lookup maps. Every map declared here should be added to
-    // clearCheckedMenus() so that they can be cleared.
-    // TODO find a better way to handle selected menu item state, when switching to fragments.
-    private Map<Long, MenuItem> mGroupMenuMap = new HashMap<>();
-    private Map<ContactListFilter, MenuItem> mFilterMenuMap = new HashMap<>();
-    private Map<Integer, MenuItem> mIdMenuMap = new HashMap<>();
-
     private Object mStatusChangeListenerHandle;
 
     private final Handler mHandler = new Handler();
@@ -284,7 +253,7 @@
     private final ProviderStatusListener mProviderStatusListener = new ProviderStatusListener() {
         @Override
         public void onProviderStatusChange() {
-            reloadGroupsAndFiltersIfNeeded();
+            // TODO see if it works with drawer fragment.
             updateViewConfiguration(false);
         }
     };
@@ -350,7 +319,6 @@
             if (newState != DrawerLayout.STATE_IDLE) {
                 updateStatusBarBackground();
             }
-            initializeAssistantNewBadge();
         }
     }
 
@@ -402,9 +370,9 @@
 
         // Set up hamburger button.
         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+        mDrawerFragment = (DrawerFragment) getFragmentManager().findFragmentById(R.id.drawer);
         mToggle = new ContactsActionBarDrawerToggle(this, mDrawerLayout, mToolbar,
                 R.string.navigation_drawer_open, R.string.navigation_drawer_close);
-
         mDrawerLayout.setDrawerListener(mToggle);
         // Set fallback handler for when drawer is disabled.
         mToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@@ -421,14 +389,6 @@
             mCurrentView = ContactsView.ALL_CONTACTS;
         }
 
-        // Set up hamburger menu items.
-        mNavigationView = (NavigationView) findViewById(R.id.nav_view);
-        mNavigationView.setNavigationItemSelectedListener(this);
-        setUpMenu();
-
-        initializeAssistantNewBadge();
-        loadGroupsAndFilters();
-
         if (savedState != null && savedState.containsKey(KEY_NEW_GROUP_ACCOUNT)) {
             mNewGroupAccount = AccountWithDataSet.unstringify(
                     savedState.getString(KEY_NEW_GROUP_ACCOUNT));
@@ -451,33 +411,6 @@
         getWindow().setBackgroundDrawable(null);
     }
 
-    private void loadGroupsAndFilters() {
-        final FragmentManager fragmentManager = getFragmentManager();
-        final FragmentTransaction transaction = fragmentManager.beginTransaction();
-        addGroupsAndFiltersFragments(transaction);
-        transaction.commitAllowingStateLoss();
-        fragmentManager.executePendingTransactions();
-    }
-
-    private void addGroupsAndFiltersFragments(FragmentTransaction transaction) {
-        final FragmentManager fragmentManager = getFragmentManager();
-        GroupsFragment groupsFragment =
-                (GroupsFragment) fragmentManager.findFragmentByTag(TAG_GROUPS);
-        if (groupsFragment == null) {
-            groupsFragment = new GroupsFragment();
-            transaction.add(groupsFragment, TAG_GROUPS);
-        }
-        groupsFragment.setListener(this);
-
-        AccountFiltersFragment accountFiltersFragment =
-                (AccountFiltersFragment) fragmentManager.findFragmentByTag(TAG_FILTERS);
-        if (accountFiltersFragment == null) {
-            accountFiltersFragment = new AccountFiltersFragment();
-            transaction.add(accountFiltersFragment, TAG_FILTERS);
-        }
-        accountFiltersFragment.setListener(this);
-    }
-
     @Override
     protected void onNewIntent(Intent intent) {
         final String action = intent.getAction();
@@ -762,20 +695,6 @@
         }
     }
 
-    private void reloadGroupsAndFiltersIfNeeded() {
-        final int providerStatus = mProviderStatusWatcher.getProviderStatus();
-        final Menu menu = mNavigationView.getMenu();
-        final MenuItem groupsMenuItem = menu.findItem(R.id.nav_groups);
-        final SubMenu subMenu = groupsMenuItem.getSubMenu();
-
-        // Reload groups and filters if provider status changes to "normal" and there's no groups
-        // loaded or just a "Create new..." menu item is in the menu.
-        if (subMenu != null && subMenu.size() <= 1 && providerStatus == ProviderStatus.STATUS_NORMAL
-                && !mProviderStatus.equals(providerStatus)) {
-            loadGroupsAndFilters();
-        }
-    }
-
     private void updateViewConfiguration(boolean forceUpdate) {
         int providerStatus = mProviderStatusWatcher.getProviderStatus();
         if (!forceUpdate && (mProviderStatus != null)
@@ -859,7 +778,7 @@
 
         // Handle the back event in drawer first.
         if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
-            mDrawerLayout.closeDrawer(GravityCompat.START);
+            closeDrawer();
             return;
         }
 
@@ -1011,7 +930,7 @@
         }
     }
 
-    private void onGroupMenuItemClicked(long groupId, String title) {
+    private void onGroupMenuItemClicked(long groupId) {
         if (isGroupView() && mMembersFragment != null
                 && mMembersFragment.isCurrentGroup(groupId)) {
             return;
@@ -1084,15 +1003,10 @@
         }
         mShouldSwitchToAllContacts = false;
         mCurrentView = ContactsView.ALL_CONTACTS;
+        mDrawerFragment.setNavigationItemChecked(ContactsView.ALL_CONTACTS);
         showFabWithAnimation(/* showFab */ true);
         mContactsListFragment.scrollToTop();
-
         resetFilter();
-
-        final Menu menu = mNavigationView.getMenu();
-        final MenuItem allContacts = menu.findItem(R.id.nav_all_contacts);
-        updateMenuSelection(allContacts);
-
         setTitle(getString(R.string.contactsList));
     }
 
@@ -1131,10 +1045,6 @@
         return mMembersFragment;
     }
 
-    protected GroupMetaData getGroupMetaData() {
-        return mMembersFragment == null ? null : mMembersFragment.getGroupMetaData();
-    }
-
     private void handleFilterChangeForFragment(ContactListFilter filter) {
         if (mContactsListFragment.canSetActionBar()) {
             mContactsListFragment.setFilterAndUpdateTitle(filter);
@@ -1152,9 +1062,6 @@
             mShouldSwitchToAllContacts = true;
         }
 
-        // Check menu in navigation drawer.
-        updateFilterMenu(filter);
-
         if (CompatUtils.isNCompatible()) {
             getWindow().getDecorView()
                     .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
@@ -1162,26 +1069,9 @@
         invalidateOptionsMenu();
     }
 
-    private void initializeAssistantNewBadge() {
-        if (mNavigationView == null) {
-            return;
-        }
-        final MenuItem assistantMenu = mNavigationView.getMenu().findItem(R.id.nav_assistant);
-        if (assistantMenu == null) {
-            return;
-        }
-        final LinearLayout newBadgeFrame =
-                (LinearLayout) MenuItemCompat.getActionView(assistantMenu);
-        final boolean showWelcomeBadge = !SharedPreferenceUtil.isWelcomeCardDismissed(this);
-        if (showWelcomeBadge && newBadgeFrame.getChildCount() == 0) {
-            if (mAssistantNewBadge == null) {
-                mAssistantNewBadge = (TextView) LayoutInflater.from(this)
-                        .inflate(R.layout.assistant_new_badge, null);
-            }
-            newBadgeFrame.setGravity(Gravity.CENTER_VERTICAL);
-            newBadgeFrame.addView(mAssistantNewBadge);
-        } else if (!showWelcomeBadge && newBadgeFrame.getChildCount() > 0) {
-            newBadgeFrame.removeAllViews();
+    public void updateDrawerGroupMenu(long groupId) {
+        if (mDrawerFragment != null) {
+            mDrawerFragment.updateGroupMenu(groupId);
         }
     }
 
@@ -1201,31 +1091,6 @@
         }
     }
 
-    private void setUpMenu() {
-        final Menu menu = mNavigationView.getMenu();
-
-        if (ObjectFactory.getAssistantFragment() == null) {
-            menu.removeItem(R.id.nav_assistant);
-        } else {
-            final int id = R.id.nav_assistant;
-            final MenuItem assistantMenu = menu.findItem(id);
-            mIdMenuMap.put(id, assistantMenu);
-            if (isAssistantView()) {
-                updateMenuSelection(assistantMenu);
-            }
-        }
-
-        if (!HelpUtils.isHelpAndFeedbackAvailable()) {
-            menu.removeItem(R.id.nav_help);
-        }
-
-        final MenuItem allContactsMenu = menu.findItem(R.id.nav_all_contacts);
-        mIdMenuMap.put(R.id.nav_all_contacts, allContactsMenu);
-        if (isAllContactsView()) {
-            updateMenuSelection(allContactsMenu);
-        }
-    }
-
     public Toolbar getToolbar() {
         return mToolbar;
     }
@@ -1242,90 +1107,6 @@
         mToggle.onConfigurationChanged(newConfig);
     }
 
-    @Override
-    public void onGroupsLoaded(List<GroupListItem> groupListItems,
-            boolean areGroupWritableAccountsAvailable) {
-        final Menu menu = mNavigationView.getMenu();
-        final MenuItem groupsMenuItem = menu.findItem(R.id.nav_groups);
-        final SubMenu subMenu = groupsMenuItem.getSubMenu();
-        subMenu.removeGroup(R.id.nav_groups_items);
-        mGroupMenuMap = new HashMap<>();
-
-        final GroupMetaData groupMetaData = getGroupMetaData();
-
-        if (groupListItems != null) {
-            // Add each group
-            for (final GroupListItem groupListItem : groupListItems) {
-                if (GroupUtil.isEmptyFFCGroup(groupListItem)) {
-                    continue;
-                }
-                final String title = groupListItem.getTitle();
-                final MenuItem menuItem =
-                        subMenu.add(R.id.nav_groups_items, Menu.NONE, Menu.NONE, title);
-                mGroupMenuMap.put(groupListItem.getGroupId(), menuItem);
-                if (isGroupView() && groupMetaData != null
-                        && groupMetaData.groupId == groupListItem.getGroupId()) {
-                    updateMenuSelection(menuItem);
-                }
-                menuItem.setIcon(R.drawable.quantum_ic_label_vd_theme_24);
-                menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
-                    @Override
-                    public boolean onMenuItemClick(MenuItem item) {
-                        onGroupMenuItemClicked(groupListItem.getGroupId(),
-                                groupListItem.getTitle());
-                        updateMenuSelection(menuItem);
-                        mDrawerLayout.closeDrawer(GravityCompat.START);
-                        return true;
-                    }
-                });
-
-                updateMenuContentDescription(menuItem,
-                        getString(R.string.group_edit_field_hint_text));
-            }
-        }
-
-        // Don't show "Create label" menu if there's no group-writable accounts available.
-        if (!areGroupWritableAccountsAvailable) {
-            return;
-        }
-
-        // Create a menu item in the sub menu to add new groups
-        final MenuItem menuItem = subMenu.add(R.id.nav_groups_items, Menu.NONE,
-                Menu.NONE, getString(R.string.menu_new_group_action_bar));
-        menuItem.setIcon(R.drawable.quantum_ic_add_vd_theme_24);
-        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                onCreateGroupMenuItemClicked();
-                mDrawerLayout.closeDrawer(GravityCompat.START);
-                return true;
-            }
-        });
-
-        if (isGroupView() && groupMetaData != null) {
-            updateGroupMenu(groupMetaData);
-        }
-    }
-
-    public void updateGroupMenu(GroupMetaData groupMetaData) {
-        clearCheckedMenus();
-        if (groupMetaData != null && mGroupMenuMap != null
-                && mGroupMenuMap.get(groupMetaData.groupId) != null) {
-            setMenuChecked(mGroupMenuMap.get(groupMetaData.groupId), true);
-        }
-    }
-
-    private void updateMenuContentDescription(MenuItem menuItem, CharSequence contentDescription) {
-        // Create a dummy action view to attach extra hidden content description to the menuItem
-        // for Talkback. We want Talkback to read out the account type but not have it be part
-        // of the menuItem title.
-        final LinearLayout view = (LinearLayout) LayoutInflater.from(this)
-                .inflate(R.layout.menu_item_action_view, null);
-        view.setContentDescription(contentDescription);
-        view.setVisibility(View.VISIBLE);
-        menuItem.setActionView(view);
-    }
-
     protected void onCreateGroupMenuItemClicked() {
         // Select the account to create the group
         final Bundle extras = getIntent().getExtras();
@@ -1363,6 +1144,7 @@
                 TAG_SELECT_ACCOUNT_DIALOG);
     }
 
+    // Implementation of SelectAccountDialogFragment.Listener
     @Override
     public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
         mNewGroupAccount = account;
@@ -1375,90 +1157,53 @@
     public void onAccountSelectorCancelled() {
     }
 
+    // Implementation of DrawerFragmentListener
     @Override
-    public void onFiltersLoaded(List<ContactListFilter> accountFilterItems) {
-        final AccountDisplayInfoFactory accountDisplayFactory = AccountDisplayInfoFactory.
-                fromListFilters(this, accountFilterItems);
-
-        final Menu menu = mNavigationView.getMenu();
-        final MenuItem filtersMenuItem = menu.findItem(R.id.nav_filters);
-        final SubMenu subMenu = filtersMenuItem.getSubMenu();
-        subMenu.removeGroup(R.id.nav_filters_items);
-        mFilterMenuMap = new HashMap<>();
-
-        if (accountFilterItems == null || accountFilterItems.size() < 2) {
-            return;
-        }
-
-        for (int i = 0; i < accountFilterItems.size(); i++) {
-            final ContactListFilter filter = accountFilterItems.get(i);
-            final AccountDisplayInfo displayableAccount =
-                    accountDisplayFactory.getAccountDisplayInfoFor(filter);
-            final CharSequence menuName = displayableAccount.getNameLabel();
-            final MenuItem menuItem = subMenu.add(R.id.nav_filters_items, Menu.NONE,
-                    Menu.NONE, menuName);
-            if (isAccountView() && filter == mContactListFilterController.getFilter()) {
-                updateMenuSelection(menuItem);
-            }
-            mFilterMenuMap.put(filter, menuItem);
-            final Intent intent = new Intent();
-            intent.putExtra(AccountFilterActivity.EXTRA_CONTACT_LIST_FILTER, filter);
-            menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
-                @Override
-                public boolean onMenuItemClick(MenuItem item) {
-                    onFilterMenuItemClicked(intent);
-                    updateMenuSelection(menuItem);
-                    mDrawerLayout.closeDrawer(GravityCompat.START);
-                    return true;
-                }
-            });
-            if (displayableAccount.getIcon() != null) {
-                menuItem.setIcon(displayableAccount.getIcon());
-                // Get rid of the default menu item overlay and show original account icons.
-                menuItem.getIcon().setColorFilter(Color.TRANSPARENT, PorterDuff.Mode.SRC_ATOP);
-            }
-
-            updateMenuContentDescription(menuItem, displayableAccount.getTypeLabel());
-        }
-
-        if (isAccountView()) {
-            updateFilterMenu(mContactListFilterController.getFilter());
-        }
+    public void onDrawerItemClicked(){
+        closeDrawer();
     }
 
-    public void updateFilterMenu(ContactListFilter filter) {
-        clearCheckedMenus();
-        if (filter != null && filter.isContactsFilterType()) {
-            if (mIdMenuMap != null && mIdMenuMap.get(R.id.nav_all_contacts) != null) {
-                setMenuChecked(mIdMenuMap.get(R.id.nav_all_contacts), true);
-            }
+    @Override
+    public void onContactsViewSelected(ContactsView mode) {
+        if (mode == ContactsView.ALL_CONTACTS) {
+            switchToAllContacts();
+        } else if (mode == ContactsView.ASSISTANT) {
+            launchAssistant();
         } else {
-            if (mFilterMenuMap != null && mFilterMenuMap.get(filter) != null) {
-                setMenuChecked(mFilterMenuMap.get(filter), true);
+            throw new IllegalStateException("Unknown view " + mode);
+        }
+    }
+
+    @Override
+    public void onCreateLabelButtonClicked() {
+        onCreateGroupMenuItemClicked();
+    }
+
+    @Override
+    public void onOpenSettings() {
+        new Handler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                startActivity(createPreferenceIntent());
             }
-        }
+        }, DRAWER_CLOSE_DELAY);
     }
 
-    private void clearCheckedMenus() {
-        clearCheckedMenu(mFilterMenuMap);
-        clearCheckedMenu(mGroupMenuMap);
-        clearCheckedMenu(mIdMenuMap);
+    @Override
+    public void onLaunchHelpFeedback() {
+        HelpUtils.launchHelpAndFeedbackForMainScreen(this);
     }
 
-    private void clearCheckedMenu(Map<?, MenuItem> map) {
-        final Iterator it = map.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry pair = (Map.Entry) it.next();
-            setMenuChecked(map.get(pair.getKey()), false);
-        }
+    @Override
+    public void onGroupViewSelected(GroupListItem groupListItem) {
+        onGroupMenuItemClicked(groupListItem.getGroupId());
     }
 
-    private void setMenuChecked(MenuItem menuItem, boolean checked) {
-        if (menuItem == null) {
-            return;
-        }
-        menuItem.setCheckable(checked);
-        menuItem.setChecked(checked);
+    @Override
+    public void onAccountViewSelected(ContactListFilter filter) {
+        final Intent intent = new Intent();
+        intent.putExtra(AccountFilterActivity.EXTRA_CONTACT_LIST_FILTER, filter);
+        onFilterMenuItemClicked(intent);
     }
 
     public boolean isGroupView() {
@@ -1481,39 +1226,8 @@
         return isGroupView() || isAssistantView();
     }
 
-    @Override
-    public boolean onNavigationItemSelected(@NonNull final MenuItem item) {
-        final int id = item.getItemId();
-
-        if (id == R.id.nav_settings) {
-            new Handler().postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    startActivity(createPreferenceIntent());
-                }
-            }, DRAWER_CLOSE_DELAY);
-        } else if (id == R.id.nav_help) {
-            HelpUtils.launchHelpAndFeedbackForMainScreen(this);
-        } else if (id == R.id.nav_all_contacts) {
-            switchToAllContacts();
-        } else if (id == R.id.nav_assistant) {
-            if (!isAssistantView()) {
-                launchAssistant();
-                updateMenuSelection(item);
-            }
-        } else if (item.getIntent() != null) {
-            ImplicitIntentsUtil.startActivityInApp(this, item.getIntent());
-        } else {
-            Log.w(TAG, "Unhandled navigation view item selection");
-        }
-
+    public void closeDrawer() {
         mDrawerLayout.closeDrawer(GravityCompat.START);
-        return true;
-    }
-
-    private void updateMenuSelection(MenuItem menuItem) {
-        clearCheckedMenus();
-        setMenuChecked(menuItem, true);
     }
 
     private Intent createPreferenceIntent() {
diff --git a/src/com/android/contacts/drawer/DrawerAdapter.java b/src/com/android/contacts/drawer/DrawerAdapter.java
new file mode 100644
index 0000000..959d478
--- /dev/null
+++ b/src/com/android/contacts/drawer/DrawerAdapter.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.drawer;
+
+import android.app.Activity;
+import android.graphics.PorterDuff;
+import android.support.annotation.LayoutRes;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.contacts.R;
+import com.android.contacts.activities.PeopleActivity.ContactsView;
+import com.android.contacts.group.GroupListItem;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contacts.model.account.AccountDisplayInfo;
+import com.android.contacts.model.account.AccountDisplayInfoFactory;
+import com.android.contacts.util.SharedPreferenceUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DrawerAdapter extends RecyclerView.Adapter {
+
+    private static final int VIEW_TYPE_PRIMARY_ITEM = 0;
+    private static final int VIEW_TYPE_MISC_ITEM = 1;
+    private static final int VIEW_TYPE_HEADER_ITEM = 2;
+    private static final int VIEW_TYPE_GROUP_ENTRY = 3;
+    private static final int VIEW_TYPE_ACCOUNT_ENTRY = 4;
+    private static final int VIEW_TYPE_CREATE_LABEL = 5;
+    private static final int VIEW_TYPE_NAV_SPACER = 6;
+    private static final int VIEW_TYPE_NAV_DIVIDER = 7;
+
+    private static final int TYPEFACE_STYLE_ACTIVATE = R.style.DrawerItemTextActiveStyle;
+    private static final int TYPEFACE_STYLE_INACTIVE = R.style.DrawerItemTextInactiveStyle;
+
+    private final Activity mActivity;
+    private final LayoutInflater mInflater;
+    private ContactsView mSelectedView;
+    private boolean mAreGroupWritableAccountsAvailable;
+
+    // The group/account that was last clicked.
+    private long mSelectedGroupId;
+    private ContactListFilter mSelectedAccount;
+
+    // Adapter elements, ordered in this way in the getItem() method. The ordering is based on:
+    //  [Navigation spacer item]
+    //  [Primary items] (Contacts, Suggestions)
+    //  [Group Header]
+    //  [Groups]
+    //  [Create Label button]
+    //  [Account Header]
+    //  [Accounts]
+    //  [Misc items] (a divider, Settings, Help & Feedback)
+    //  [Navigation spacer item]
+    private NavSpacerItem mNavSpacerItem = null;
+    private List<PrimaryItem> mPrimaryItems = new ArrayList<>();
+    private HeaderItem mGroupHeader = null;
+    private List<GroupEntryItem> mGroupEntries = new ArrayList<>();
+    private BaseDrawerItem mCreateLabelButton = null;
+    private HeaderItem mAccountHeader = null;
+    private List<AccountEntryItem> mAccountEntries = new ArrayList<>();
+    private List<BaseDrawerItem> mMiscItems = new ArrayList<>();
+
+    private List<BaseDrawerItem> mItemsList = new ArrayList<>();
+    private OnClickListener mListener;
+    private AccountDisplayInfoFactory mAccountDisplayFactory;
+
+    public DrawerAdapter(Activity activity) {
+        super();
+        mInflater = LayoutInflater.from(activity);
+        mActivity = activity;
+        initializeDrawerMenuItems();
+    }
+
+    private void initializeDrawerMenuItems() {
+        // Spacer item for dividing sections in drawer
+        mNavSpacerItem = new NavSpacerItem(R.id.nav_drawer_spacer);
+        // Primary items
+        mPrimaryItems.add(new PrimaryItem(R.id.nav_all_contacts, R.string.contactsList,
+                R.drawable.quantum_ic_account_circle_vd_theme_24, ContactsView.ALL_CONTACTS));
+        mPrimaryItems.add(new PrimaryItem(R.id.nav_assistant, R.string.menu_assistant,
+                R.drawable.quantum_ic_assistant_vd_theme_24, ContactsView.ASSISTANT));
+        // Group Header
+        mGroupHeader = new HeaderItem(R.id.nav_groups, R.string.menu_title_groups);
+        // Account Header
+        mAccountHeader = new HeaderItem(R.id.nav_filters, R.string.menu_title_filters);
+        // Create Label Button
+        mCreateLabelButton = new BaseDrawerItem(VIEW_TYPE_CREATE_LABEL, R.id.nav_create_label,
+                R.string.menu_new_group_action_bar, R.drawable.quantum_ic_add_vd_theme_24);
+        // Misc Items
+        mMiscItems.add(new DividerItem());
+        mMiscItems.add(new MiscItem(R.id.nav_settings, R.string.menu_settings,
+                R.drawable.quantum_ic_settings_vd_theme_24));
+        mMiscItems.add(new MiscItem(R.id.nav_help, R.string.menu_help,
+                R.drawable.quantum_ic_help_vd_theme_24));
+        rebuildItemsList();
+    }
+
+    private void rebuildItemsList() {
+        mItemsList.clear();
+        mItemsList.add(mNavSpacerItem);
+        mItemsList.addAll(mPrimaryItems);
+        if (mAreGroupWritableAccountsAvailable) {
+            mItemsList.add(mGroupHeader);
+        }
+        mItemsList.addAll(mGroupEntries);
+        if (mAreGroupWritableAccountsAvailable) {
+            mItemsList.add(mCreateLabelButton);
+        }
+        if (mAccountEntries.size() > 0) {
+            mItemsList.add(mAccountHeader);
+        }
+        mItemsList.addAll(mAccountEntries);
+        mItemsList.addAll(mMiscItems);
+        mItemsList.add(mNavSpacerItem);
+    }
+
+    public void setItemOnClickListener(OnClickListener listener) {
+        mListener = listener;
+    }
+
+    public void setGroups(List<GroupListItem> groupListItems, boolean areGroupWritable) {
+        final ArrayList<GroupEntryItem> groupEntries = new ArrayList<GroupEntryItem>();
+        for (GroupListItem group : groupListItems) {
+            groupEntries.add(new GroupEntryItem(R.id.nav_group, group));
+        }
+        mGroupEntries.clear();
+        mGroupEntries.addAll(groupEntries);
+        mAreGroupWritableAccountsAvailable = areGroupWritable;
+        notifyChangeAndRebuildList();
+    }
+
+    public void setAccounts(List<ContactListFilter> accountFilterItems) {
+        ArrayList<AccountEntryItem> accountItems = new ArrayList<AccountEntryItem>();
+        for (ContactListFilter filter : accountFilterItems) {
+            accountItems.add(new AccountEntryItem(R.id.nav_filter, filter));
+        }
+        mAccountDisplayFactory = AccountDisplayInfoFactory.fromListFilters(mActivity,
+                accountFilterItems);
+        mAccountEntries.clear();
+        mAccountEntries.addAll(accountItems);
+        // TODO investigate performance of calling notifyDataSetChanged
+        notifyChangeAndRebuildList();
+    }
+
+    @Override
+    public int getItemCount() {
+        return  mItemsList.size();
+    }
+
+    public BaseDrawerItem getItem(int position) {
+        return mItemsList.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).id;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return getItem(position).viewType;
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        switch (viewType) {
+            case VIEW_TYPE_NAV_SPACER:
+                return getBaseViewHolder(R.layout.nav_drawer_spacer, parent);
+            case VIEW_TYPE_PRIMARY_ITEM:
+                return getPrimaryItemView(parent);
+            case VIEW_TYPE_HEADER_ITEM:
+                return getHeaderItemViewHolder(parent);
+            case VIEW_TYPE_GROUP_ENTRY:
+            case VIEW_TYPE_CREATE_LABEL:
+            case VIEW_TYPE_ACCOUNT_ENTRY:
+            case VIEW_TYPE_MISC_ITEM:
+                return getDrawerItemViewHolder(parent);
+            case VIEW_TYPE_NAV_DIVIDER:
+                return getBaseViewHolder(R.layout.drawer_horizontal_divider, parent);
+        }
+        throw new IllegalStateException("Unknown view type " + viewType);
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+        final BaseDrawerItem item = getItem(position);
+        switch (item.viewType) {
+            case VIEW_TYPE_PRIMARY_ITEM:
+                bindPrimaryItemViewHolder((PrimaryItemViewHolder) holder, (PrimaryItem) item);
+                break;
+            case VIEW_TYPE_HEADER_ITEM:
+                bindHeaderItemViewHolder((HeaderItemViewHolder) holder, (HeaderItem) item);
+                break;
+            case VIEW_TYPE_GROUP_ENTRY:
+                bindGroupItemViewHolder((DrawerItemViewHolder) holder, (GroupEntryItem) item);
+                break;
+            case VIEW_TYPE_ACCOUNT_ENTRY:
+                bindAccountViewHolder((DrawerItemViewHolder) holder, (AccountEntryItem) item);
+                break;
+            case VIEW_TYPE_CREATE_LABEL:
+            case VIEW_TYPE_MISC_ITEM:
+                bindDrawerItemViewHolder((DrawerItemViewHolder) holder, item);
+                break;
+        }
+    }
+
+    private void bindPrimaryItemViewHolder(PrimaryItemViewHolder viewHolder, PrimaryItem item) {
+        viewHolder.titleView.setText(item.text);
+        viewHolder.iconView.setImageResource(item.icon);
+        viewHolder.itemView.setId(item.id);
+        viewHolder.itemView.setOnClickListener(mListener);
+        final boolean showWelcomeBadge = !SharedPreferenceUtil.isWelcomeCardDismissed(mActivity);
+        if (item.contactsView == ContactsView.ASSISTANT && showWelcomeBadge) {
+            viewHolder.newBadge.setVisibility(View.VISIBLE);
+        } else {
+            viewHolder.newBadge.setVisibility(View.GONE);
+        }
+        viewHolder.itemView.setActivated(item.contactsView == mSelectedView);
+        updateSelectedStatus(viewHolder);
+    }
+
+    private void bindHeaderItemViewHolder(HeaderItemViewHolder viewHolder, HeaderItem item) {
+        viewHolder.titleView.setText(item.text);
+        viewHolder.itemView.setId(item.id);
+    }
+
+    private void bindGroupItemViewHolder(DrawerItemViewHolder viewHolder, GroupEntryItem item) {
+        final GroupListItem group = item.group;
+        viewHolder.titleView.setText(group.getTitle());
+        viewHolder.iconView.setImageResource(R.drawable.quantum_ic_label_vd_theme_24);
+        viewHolder.itemView.setId(item.id);
+        viewHolder.itemView.setTag(group);
+        viewHolder.itemView.setOnClickListener(mListener);
+        viewHolder.itemView.setContentDescription(
+                mActivity.getString(R.string.navigation_drawer_label, group.getTitle()));
+        viewHolder.itemView.setActivated(group.getGroupId() == mSelectedGroupId
+                && mSelectedView == ContactsView.GROUP_VIEW);
+        updateSelectedStatus(viewHolder);
+    }
+
+    private void bindAccountViewHolder(DrawerItemViewHolder viewHolder, AccountEntryItem item) {
+        final ContactListFilter account = item.account;
+        viewHolder.titleView.setText(account.accountName);
+        final AccountDisplayInfo displayableAccount =
+                mAccountDisplayFactory.getAccountDisplayInfoFor(item.account);
+        viewHolder.iconView.setImageDrawable(displayableAccount.getIcon());
+        viewHolder.iconView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+        viewHolder.itemView.setId(item.id);
+        viewHolder.itemView.setTag(account);
+        viewHolder.itemView.setOnClickListener(mListener);
+        viewHolder.itemView.setContentDescription(
+                displayableAccount.getTypeLabel() + " " + account.accountName);
+        viewHolder.itemView.setActivated(account.equals(mSelectedAccount)
+                && mSelectedView == ContactsView.ACCOUNT_VIEW);
+        updateSelectedStatus(viewHolder);
+        viewHolder.iconView.clearColorFilter();
+    }
+
+    private void bindDrawerItemViewHolder(DrawerItemViewHolder viewHolder, BaseDrawerItem item) {
+        viewHolder.titleView.setText(item.text);
+        viewHolder.iconView.setImageResource(item.icon);
+        viewHolder.itemView.setId(item.id);
+        viewHolder.itemView.setOnClickListener(mListener);
+        viewHolder.itemView.setActivated(false);
+        updateSelectedStatus(viewHolder);
+    }
+
+    private void updateSelectedStatus(DrawerItemViewHolder viewHolder) {
+        final boolean activated = viewHolder.itemView.isActivated();
+        viewHolder.titleView.setTextAppearance(mActivity, activated
+                ? TYPEFACE_STYLE_ACTIVATE : TYPEFACE_STYLE_INACTIVE);
+        if (activated) {
+            viewHolder.iconView.setColorFilter(mActivity.getResources().getColor(R.color
+                    .primary_color), PorterDuff.Mode.SRC_ATOP);
+        } else {
+            viewHolder.iconView.clearColorFilter();
+        }
+    }
+
+    private BaseViewHolder getBaseViewHolder(@LayoutRes int layoutResID, ViewGroup parent) {
+        final View view = mInflater.inflate(layoutResID, parent, false);
+        return new BaseViewHolder(view);
+    }
+
+    private HeaderItemViewHolder getHeaderItemViewHolder(ViewGroup parent) {
+        final View view = mInflater.inflate(R.layout.drawer_header, parent, false);
+        return new HeaderItemViewHolder(view);
+    }
+
+    private DrawerItemViewHolder getDrawerItemViewHolder(ViewGroup parent) {
+        final View view = mInflater.inflate(R.layout.drawer_item, parent, false);
+        return new DrawerItemViewHolder(view);
+    }
+
+    private PrimaryItemViewHolder getPrimaryItemView(ViewGroup parent) {
+        final View view = mInflater.inflate(R.layout.drawer_primary_item, parent, false);
+        return new PrimaryItemViewHolder(view);
+    }
+
+    private void notifyChangeAndRebuildList() {
+        notifyDataSetChanged();
+        rebuildItemsList();
+    }
+
+    public void setSelectedContactsView(ContactsView contactsView) {
+        if (mSelectedView == contactsView) {
+            return;
+        }
+        mSelectedView = contactsView;
+        notifyChangeAndRebuildList();
+    }
+
+
+    public void setSelectedGroupId(long groupId) {
+        if (mSelectedGroupId == groupId) {
+            return;
+        }
+        mSelectedGroupId = groupId;
+        notifyChangeAndRebuildList();
+    }
+
+    public long getSelectedGroupId() {
+        return mSelectedGroupId;
+    }
+
+    public void setSelectedAccount(ContactListFilter filter) {
+        if (mSelectedAccount == filter) {
+            return;
+        }
+        mSelectedAccount = filter;
+        notifyChangeAndRebuildList();
+    }
+
+    public ContactListFilter getSelectedAccount() {
+        return mSelectedAccount;
+    }
+
+    public static class BaseDrawerItem {
+        public final int viewType;
+        public final int id;
+        public final int text;
+        public final int icon;
+
+        public BaseDrawerItem(int adapterViewType, int viewId, int textResId, int iconResId) {
+            viewType = adapterViewType;
+            id = viewId;
+            text = textResId;
+            icon = iconResId;
+        }
+    }
+
+    // Navigation drawer item for Contacts or Suggestions view which contains a name, an icon and
+    // contacts view.
+    public static class PrimaryItem extends BaseDrawerItem {
+        public final ContactsView contactsView;
+
+        public PrimaryItem(int id, int pageName, int iconId, ContactsView contactsView) {
+            super(VIEW_TYPE_PRIMARY_ITEM, id, pageName, iconId);
+            this.contactsView = contactsView;
+        }
+    }
+
+    // Navigation drawer item for Settings, help and feedback, etc.
+    public static class MiscItem extends BaseDrawerItem {
+        public MiscItem(int id, int textId, int iconId) {
+            super(VIEW_TYPE_MISC_ITEM, id, textId, iconId);
+        }
+    }
+
+    // Header for a list of sub-items in the drawer.
+    public static class HeaderItem extends BaseDrawerItem {
+        public HeaderItem(int id, int textId) {
+            super(VIEW_TYPE_HEADER_ITEM, id, textId, /* iconResId */ 0);
+        }
+    }
+
+    // Navigation drawer item for spacer item for dividing sections in the drawer.
+    public static class NavSpacerItem extends BaseDrawerItem {
+        public NavSpacerItem(int id) {
+            super(VIEW_TYPE_NAV_SPACER, id, /* textResId */ 0, /* iconResId */ 0);
+        }
+    }
+
+    // Divider for drawing a line between sections in the drawer.
+    public static class DividerItem extends BaseDrawerItem {
+        public DividerItem() {
+            super(VIEW_TYPE_NAV_DIVIDER, /* id */ 0, /* textResId */ 0, /* iconResId */ 0);
+        }
+    }
+
+    // Navigation drawer item for a group.
+    public static class GroupEntryItem extends BaseDrawerItem {
+        private final GroupListItem group;
+
+        public GroupEntryItem(int id, GroupListItem group) {
+            super(VIEW_TYPE_GROUP_ENTRY, id, /* textResId */ 0, /* iconResId */ 0);
+            this.group = group;
+        }
+    }
+
+    // Navigation drawer item for an account.
+    public static class AccountEntryItem extends BaseDrawerItem {
+        private final ContactListFilter account;
+
+        public AccountEntryItem(int id, ContactListFilter account) {
+            super(VIEW_TYPE_ACCOUNT_ENTRY, id, /* textResId */ 0, /* iconResId */ 0);
+            this.account = account;
+        }
+    }
+
+    /**
+     * ViewHolder classes
+     */
+    public static class BaseViewHolder extends RecyclerView.ViewHolder {
+        public BaseViewHolder(View itemView) {
+            super(itemView);
+        }
+    }
+
+    public static class HeaderItemViewHolder extends BaseViewHolder {
+        public final TextView titleView;
+
+        public HeaderItemViewHolder(View itemView) {
+            super(itemView);
+            titleView = (TextView) itemView.findViewById(R.id.title);
+        }
+    }
+
+    public class DrawerItemViewHolder extends HeaderItemViewHolder {
+        public final ImageView iconView;
+
+        public DrawerItemViewHolder(View itemView) {
+            super(itemView);
+            iconView = (ImageView) itemView.findViewById(R.id.icon);
+        }
+    }
+
+    public class PrimaryItemViewHolder extends DrawerItemViewHolder {
+        public final TextView newBadge;
+
+        public PrimaryItemViewHolder(View itemView) {
+            super(itemView);
+            newBadge = (TextView) itemView.findViewById(R.id.assistant_new_badge);
+        }
+    }
+}
diff --git a/src/com/android/contacts/drawer/DrawerFragment.java b/src/com/android/contacts/drawer/DrawerFragment.java
new file mode 100644
index 0000000..b57f151
--- /dev/null
+++ b/src/com/android/contacts/drawer/DrawerFragment.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.drawer;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.contacts.R;
+import com.android.contacts.activities.PeopleActivity.ContactsView;
+import com.android.contacts.group.GroupListItem;
+import com.android.contacts.group.GroupUtil;
+import com.android.contacts.group.GroupsFragment;
+import com.android.contacts.group.GroupsFragment.GroupsListener;
+import com.android.contacts.interactions.AccountFiltersFragment;
+import com.android.contacts.interactions.AccountFiltersFragment.AccountFiltersListener;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contactsbind.ObjectFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class DrawerFragment extends Fragment implements AccountFiltersListener, GroupsListener {
+
+    private WelcomeContentObserver mObserver;
+    private RecyclerView mDrawerRecyclerView;
+    private DrawerAdapter mDrawerAdapter;
+    private ContactsView mCurrentContactsView;
+    private DrawerFragmentListener mListener;
+    private GroupsFragment mGroupsFragment;
+    private AccountFiltersFragment mAccountFiltersFragment;
+
+    private static final String TAG_GROUPS = "groups";
+    private static final String TAG_FILTERS = "filters";
+    private static final String KEY_CONTACTS_VIEW = "contactsView";
+    private static final String KEY_SELECTED_GROUP = "selectedGroup";
+    private static final String KEY_SELECTED_ACCOUNT = "selectedAccount";
+
+    private final class WelcomeContentObserver extends ContentObserver {
+        private WelcomeContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            mDrawerAdapter.notifyDataSetChanged();
+        }
+    }
+
+    public DrawerFragment() {}
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        if (activity instanceof DrawerFragmentListener) {
+            mListener = (DrawerFragmentListener) activity;
+        } else {
+            throw new IllegalArgumentException(
+                    "Activity must implement " + DrawerFragmentListener.class.getName());
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View contentView = inflater.inflate(R.layout.drawer_fragment, null);
+        mDrawerRecyclerView = (RecyclerView) contentView.findViewById(R.id.list);
+        mDrawerRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+        mDrawerAdapter = new DrawerAdapter(getActivity());
+        mDrawerAdapter.setSelectedContactsView(mCurrentContactsView);
+        mDrawerAdapter.setItemOnClickListener(mOnDrawerItemClickListener);
+        loadGroupsAndFilters();
+        mDrawerRecyclerView.setAdapter(mDrawerAdapter);
+
+        if (savedInstanceState != null) {
+            final ContactsView contactsView =
+                    ContactsView.values()[savedInstanceState.getInt(KEY_CONTACTS_VIEW)];
+            setNavigationItemChecked(contactsView);
+            final long groupId = savedInstanceState.getLong(KEY_SELECTED_GROUP);
+            mDrawerAdapter.setSelectedGroupId(groupId);
+            final ContactListFilter filter = savedInstanceState.getParcelable(KEY_SELECTED_ACCOUNT);
+            mDrawerAdapter.setSelectedAccount(filter);
+        } else {
+            setNavigationItemChecked(ContactsView.ALL_CONTACTS);
+        }
+
+        return contentView;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // todo double check on the new Handler() thing
+        final Uri uri = ObjectFactory.getWelcomeUri();
+        if (uri != null) {
+            mObserver = new WelcomeContentObserver(new Handler());
+            getActivity().getContentResolver().registerContentObserver(uri, false, mObserver);
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt(KEY_CONTACTS_VIEW, mCurrentContactsView.ordinal());
+        outState.putLong(KEY_SELECTED_GROUP, mDrawerAdapter.getSelectedGroupId());
+        outState.putParcelable(KEY_SELECTED_ACCOUNT, mDrawerAdapter.getSelectedAccount());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mObserver != null) {
+            getActivity().getContentResolver().unregisterContentObserver(mObserver);
+        }
+    }
+
+    // TODO create loaders in this fragment instead of having separate fragments that just kick off
+    // some data loading.
+    private void loadGroupsAndFilters() {
+        final FragmentManager fragmentManager = getFragmentManager();
+        final FragmentTransaction transaction = fragmentManager.beginTransaction();
+        mGroupsFragment = (GroupsFragment) fragmentManager.findFragmentByTag(TAG_GROUPS);
+        if (mGroupsFragment == null) {
+            mGroupsFragment = new GroupsFragment();
+            transaction.add(mGroupsFragment, TAG_GROUPS);
+        }
+        mGroupsFragment.setListener(this);
+
+        mAccountFiltersFragment = (AccountFiltersFragment)
+                fragmentManager.findFragmentByTag(TAG_FILTERS);
+        if (mAccountFiltersFragment == null) {
+            mAccountFiltersFragment = new AccountFiltersFragment();
+            transaction.add(mAccountFiltersFragment, TAG_FILTERS);
+        }
+        mAccountFiltersFragment.setListener(this);
+        transaction.commitAllowingStateLoss();
+        fragmentManager.executePendingTransactions();
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        mListener = null;
+    }
+
+    private final View.OnClickListener mOnDrawerItemClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (mListener == null) {
+                return;
+            }
+            mListener.onDrawerItemClicked();
+            final int viewId = v.getId();
+            if (viewId == R.id.nav_all_contacts) {
+                mListener.onContactsViewSelected(ContactsView.ALL_CONTACTS);
+                setNavigationItemChecked(ContactsView.ALL_CONTACTS);
+            } else if (viewId == R.id.nav_assistant) {
+                mListener.onContactsViewSelected(ContactsView.ASSISTANT);
+                setNavigationItemChecked(ContactsView.ASSISTANT);
+            } else if (viewId == R.id.nav_group) {
+                final GroupListItem groupListItem = (GroupListItem) v.getTag();
+                mListener.onGroupViewSelected(groupListItem);
+                mDrawerAdapter.setSelectedGroupId(groupListItem.getGroupId());
+                setNavigationItemChecked(ContactsView.GROUP_VIEW);
+            } else if (viewId == R.id.nav_filter) {
+                final ContactListFilter filter = (ContactListFilter) v.getTag();
+                mListener.onAccountViewSelected(filter);
+                mDrawerAdapter.setSelectedAccount(filter);
+                setNavigationItemChecked(ContactsView.ACCOUNT_VIEW);
+            } else if (viewId == R.id.nav_create_label) {
+                mListener.onCreateLabelButtonClicked();
+            } else if (viewId == R.id.nav_settings) {
+                mListener.onOpenSettings();
+            } else if (viewId == R.id.nav_help) {
+                mListener.onLaunchHelpFeedback();
+            } else {
+                throw new IllegalStateException("Unknown view");
+            }
+        }
+    };
+
+    public void setNavigationItemChecked(ContactsView contactsView) {
+        mCurrentContactsView = contactsView;
+        if (mDrawerAdapter != null) {
+            mDrawerAdapter.setSelectedContactsView(contactsView);
+        }
+    }
+
+    @Override
+    public void onGroupsLoaded(List<GroupListItem> groupListItems, boolean areGroupWritable) {
+        final Iterator<GroupListItem> iterator = groupListItems.iterator();
+        while (iterator.hasNext()) {
+            final GroupListItem groupListItem = iterator.next();
+            if (GroupUtil.isEmptyFFCGroup(groupListItem)) {
+                iterator.remove();
+            }
+        }
+        mDrawerAdapter.setGroups(groupListItems, areGroupWritable);
+    }
+
+    public void updateGroupMenu(long groupId) {
+        mDrawerAdapter.setSelectedGroupId(groupId);
+        setNavigationItemChecked(ContactsView.GROUP_VIEW);
+    }
+
+    @Override
+    public void onFiltersLoaded(List<ContactListFilter> accountFilterItems) {
+        if (accountFilterItems == null || accountFilterItems.size() < 2) {
+            mDrawerAdapter.setAccounts(new ArrayList<ContactListFilter>());
+        } else {
+            mDrawerAdapter.setAccounts(accountFilterItems);
+        }
+    }
+
+    public interface DrawerFragmentListener {
+        void onDrawerItemClicked();
+        void onContactsViewSelected(ContactsView mode);
+        void onGroupViewSelected(GroupListItem groupListItem);
+        void onAccountViewSelected(ContactListFilter filter);
+        void onCreateLabelButtonClicked();
+        void onOpenSettings();
+        void onLaunchHelpFeedback();
+    }
+}
diff --git a/src/com/android/contacts/group/GroupMembersFragment.java b/src/com/android/contacts/group/GroupMembersFragment.java
index 31938d7..0d2410d 100644
--- a/src/com/android/contacts/group/GroupMembersFragment.java
+++ b/src/com/android/contacts/group/GroupMembersFragment.java
@@ -730,8 +730,8 @@
         maybeAttachCheckBoxListener();
 
         mActivity.setTitle(mGroupMetaData.groupName);
-        mActivity.updateGroupMenu(mGroupMetaData);
         mActivity.invalidateOptionsMenu();
+        mActivity.updateDrawerGroupMenu(mGroupMetaData.groupId);
 
         // Start loading the group members
         super.startLoading();