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();