Show account filters in navigation drawer
- Remove the blue rectangle and use a white background of height 24dp.
- Navigation drawer design: https://docs.google.com/a/google.com/document/d/1oVptSYWa84CGt2mIQxmRObLVqopJUUilZxlARCJaiMs/edit?usp=sharing
- The external text "labels" corresponds to "groups" in code; the text
"Accounts" corresponds to "filters" in code.
- Avoid opening AccountFilterActivity from filter header.
Bug 27687799
Bug 28245667
Fixes 28245762
Fixes 28245372
Change-Id: I75efa2fca05a1c5b74051f43e342a61f937602a1
diff --git a/res/drawable/side_nav_bar.xml b/res/drawable/side_nav_bar.xml
deleted file mode 100644
index b67bfb5..0000000
--- a/res/drawable/side_nav_bar.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <gradient
- android:angle="135"
- android:endColor="@color/primary_color_dark"
- android:startColor="@color/primary_color"
- android:type="linear"/>
-</shape>
\ No newline at end of file
diff --git a/res/layout/nav_header_main.xml b/res/layout/nav_header_main.xml
index cd6d559..37a33f4 100644
--- a/res/layout/nav_header_main.xml
+++ b/res/layout/nav_header_main.xml
@@ -20,7 +20,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
- android:background="@drawable/side_nav_bar"
+ android:background="@color/contacts_accent_color"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="@dimen/nav_activity_vertical_margin"
diff --git a/res/menu/activity_main_drawer.xml b/res/menu/activity_main_drawer.xml
index 2a69763..75277af 100644
--- a/res/menu/activity_main_drawer.xml
+++ b/res/menu/activity_main_drawer.xml
@@ -20,13 +20,9 @@
<group android:id="@+id/nav_utilities">
<item
- android:id="@+id/nav_contacts_filter"
+ android:id="@+id/nav_all_contacts"
android:icon="@drawable/ic_menu_filter"
- android:title="@string/menu_contacts_filter" />
- <item
- android:id="@+id/nav_import_export"
- android:icon="@drawable/ic_menu_import_export"
- android:title="@string/menu_import_export"/>
+ android:title="@string/contactsList" />
<item
android:id="@+id/nav_blocked_numbers"
android:icon="@drawable/ic_menu_blocked_numbers"
@@ -37,12 +33,40 @@
android:title="@string/menu_duplicates"/>
</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/create_groups">
+ <item
+ android:id="@+id/nav_create_groups"
+ android:icon="@drawable/ic_menu_group_add"
+ android:title="@string/menu_new_group_action_bar"
+ android:visible="false"/>
+ </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/ic_menu_settings"
android:title="@string/menu_settings"/>
<item
+ android:id="@+id/nav_import_export"
+ android:icon="@drawable/ic_menu_import_export"
+ android:title="@string/menu_import_export"/>
+ <item
android:id="@+id/nav_help"
android:icon="@drawable/ic_menu_help"
android:title="@string/menu_help"/>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c429ec9..f60670c 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -291,8 +291,8 @@
<!-- Top margin for "Saving to" account header text field. -->
<dimen name="compact_editor_account_header_top_margin">3dp</dimen>
- <!-- Navigation drawer header height, per the Android Design guidelines. -->
- <dimen name="nav_header_height">160dp</dimen>
+ <!-- Navigation drawer header height, the same as the status bar in landscape and portrait modes -->
+ <dimen name="nav_header_height">24dp</dimen>
<!-- Navigation drawer margins, per the Android Design guidelines. -->
<dimen name="nav_activity_horizontal_margin">16dp</dimen>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index b0470b5..f5649d9 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -48,8 +48,8 @@
<item type="id" name="nav_misc" />
<!-- Menu group ID for the contact groups -->
- <item type="id" name="nav_groups" />
+ <item type="id" name="nav_groups_items" />
- <!-- Menu group ID for "create new group" -->
- <item type="id" name="nav_create_groups" />
+ <!-- Menu group ID for the contact filters -->
+ <item type="id" name="nav_filters_items" />
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e1b857..829671f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -928,4 +928,10 @@
<!-- Close drawer content descriptions [CHAR LIMIT=40] -->
<string name="navigation_drawer_close">Close navigation drawer</string>
+
+ <!-- Menu section title of "labels" [CHAR LIMIT=20] -->
+ <string name="menu_title_groups">Labels</string>
+
+ <!-- Menu section title of "accounts" [CHAR LIMIT=20] -->
+ <string name="menu_title_filters">Accounts</string>
</resources>
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index c1a3018..9ac37bb 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -25,6 +25,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
@@ -39,6 +41,7 @@
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.telecom.TelecomManager;
import android.text.TextUtils;
@@ -48,6 +51,7 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
@@ -61,6 +65,7 @@
import com.android.contacts.common.compat.BlockedNumberContractCompat;
import com.android.contacts.common.compat.TelecomManagerUtil;
import com.android.contacts.common.interactions.ImportExportDialogFragment;
+import com.android.contacts.common.list.AccountFilterActivity;
import com.android.contacts.common.list.ContactEntryListFragment;
import com.android.contacts.common.list.ContactListFilter;
import com.android.contacts.common.list.ContactListFilterController;
@@ -79,6 +84,8 @@
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.interactions.ContactMultiDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
@@ -109,6 +116,7 @@
public class PeopleActivity extends AppCompatContactsActivity implements
View.OnCreateContextMenuListener,
View.OnClickListener,
+ AccountFiltersListener,
ActionBarAdapter.Listener,
DialogManager.DialogShowingViewActivity,
ContactListFilterController.ContactListFilterListener,
@@ -148,6 +156,7 @@
*/
private MultiSelectContactsListFragment mAllFragment;
private GroupsFragment mGroupsFragment;
+ private AccountFiltersFragment mAccountFiltersFragment;
/** ViewPager for swipe */
private ViewPager mTabPager;
@@ -360,6 +369,7 @@
final String ALL_TAG = "tab-pager-all";
final String GROUPS_TAG = "groups";
+ final String FILTERS_TAG = "filters";
// Create the fragments and add as children of the view pager.
// The pager adapter will only change the visibility; it'll never create/destroy
@@ -371,6 +381,8 @@
fragmentManager.findFragmentByTag(ALL_TAG);
mGroupsFragment = (GroupsFragment)
fragmentManager.findFragmentByTag(GROUPS_TAG);
+ mAccountFiltersFragment = (AccountFiltersFragment)
+ fragmentManager.findFragmentByTag(FILTERS_TAG);
if (mAllFragment == null) {
mAllFragment = new MultiSelectContactsListFragment();
@@ -380,6 +392,9 @@
mGroupsFragment = new GroupsFragment();
transaction.add(mGroupsFragment, GROUPS_TAG);
}
+
+ mAccountFiltersFragment = new AccountFiltersFragment();
+ transaction.add(mAccountFiltersFragment, FILTERS_TAG);
}
mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());
@@ -389,6 +404,8 @@
mGroupsFragment.setListener(this);
}
+ mAccountFiltersFragment.setListener(this);
+
// Hide all fragments for now. We adjust visibility when we get onSelectedTabChanged()
// from ActionBarAdapter.
transaction.hide(mAllFragment);
@@ -894,43 +911,56 @@
@Override
public void onGroupsLoaded(List<GroupListItem> groupListItems) {
- // Clear previously added groups
final Menu menu = mNavigationView.getMenu();
- menu.removeGroup(R.id.nav_groups);
+ final MenuItem groupsMenuItem = menu.findItem(R.id.nav_groups);
+ final SubMenu subMenu = groupsMenuItem.getSubMenu();
+ subMenu.removeGroup(R.id.nav_groups_items);
- if (groupListItems == null || groupListItems.isEmpty()) {
+ if (groupListItems != null) {
+ // Add each group
+ for (GroupListItem groupListItem : groupListItems) {
+ final String title = groupListItem.getTitle();
+ final MenuItem menuItem =
+ subMenu.add(R.id.nav_groups_items, Menu.NONE, Menu.NONE, title);
+ menuItem.setIntent(GroupUtil.createViewGroupIntent(this, groupListItem.getGroupId()));
+ menuItem.setIcon(R.drawable.ic_menu_label);
+ }
+ }
+
+ makeMenuItemVisible(menu, R.id.nav_create_groups, areGroupWritableAccountsAvailable());
+ }
+
+ @Override
+ public void onFiltersLoaded(List<ContactListFilter> 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);
+
+ if (accountFilterItems == null || accountFilterItems.size() < 2) {
return;
}
- // Add each group
- for (GroupListItem groupListItem : groupListItems) {
- final String title = groupListItem.getTitle();
- final MenuItem menuItem = menu.add(R.id.nav_groups, Menu.NONE, Menu.NONE, title);
- menuItem.setIntent(GroupUtil.createViewGroupIntent(this, groupListItem.getGroupId()));
- menuItem.setIcon(R.drawable.ic_menu_label);
- }
-
- menu.removeGroup(R.id.nav_create_groups);
- // Create a menu item to add new groups
- final MenuItem menuItem = menu.add(R.id.nav_create_groups, Menu.NONE, Menu.NONE,
- getString(R.string.menu_new_group_action_bar));
- menuItem.setIntent(GroupUtil.createAddGroupIntent(this));
- menuItem.setIcon(R.drawable.ic_menu_group_add);
-
- // Add misc menu items below the group of groups menu items
- addMiscMenuItems();
- }
-
- private void addMiscMenuItems() {
- final Menu menu = mNavigationView.getMenu();
- menu.removeGroup(R.id.nav_misc);
- final MenuItem settingsItem = menu.add(R.id.nav_misc, R.id.nav_settings, Menu.NONE,
- R.string.menu_settings);
- settingsItem.setIcon(R.drawable.ic_menu_settings);
- if (HelpUtils.isHelpAndFeedbackAvailable()) {
- final MenuItem helpItem = menu.add(R.id.nav_misc, R.id.nav_help, Menu.NONE,
- R.string.menu_help);
- helpItem.setIcon(R.drawable.ic_menu_help);
+ for (int i = 0; i < accountFilterItems.size(); i++) {
+ final ContactListFilter filter = accountFilterItems.get(i);
+ final String accountName = filter.accountName;
+ final MenuItem menuItem = subMenu.add(R.id.nav_filters_items, Menu.NONE, Menu.NONE,
+ accountName);
+ final Intent intent = new Intent();
+ intent.putExtra(AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER, filter);
+ menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ drawer.closeDrawer(GravityCompat.START);
+ AccountFilterUtil.handleAccountFilterResult(
+ mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
+ return true;
+ }
+ });
+ menuItem.setIcon(filter.icon);
+ // Get rid of the default memu item overlay and show original account icons.
+ menuItem.getIcon().setColorFilter(Color.TRANSPARENT, PorterDuff.Mode.SRC_ATOP);
}
}
@@ -1201,10 +1231,13 @@
startActivity(new Intent(this, ContactsPreferenceActivity.class));
} else if (id == R.id.nav_help) {
HelpUtils.launchHelpAndFeedbackForMainScreen(this);
- } else if (id == R.id.nav_contacts_filter) {
- AccountFilterUtil.startAccountFilterActivityForResult(
- this, SUBACTIVITY_ACCOUNT_FILTER,
- mContactListFilterController.getFilter());
+ } else if (id == R.id.nav_all_contacts) {
+ final Intent intent = new Intent();
+ final ContactListFilter filter = ContactListFilter.createFilterWithType(
+ ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+ intent.putExtra(AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER, filter);
+ AccountFilterUtil.handleAccountFilterResult(
+ mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
} else if (id == R.id.nav_import_export) {
showImportExportDialogFragment();
} else if (id == R.id.nav_blocked_numbers) {
@@ -1216,6 +1249,8 @@
} else if (id == R.id.nav_find_duplicates) {
ImplicitIntentsUtil.startActivityInAppIfPossible(this,
Assistants.getDuplicatesActivityIntent(this));
+ } else if (id == R.id.nav_create_groups) {
+ ImplicitIntentsUtil.startActivityInApp(this, GroupUtil.createAddGroupIntent(this));
} else if (item.getIntent() != null) {
ImplicitIntentsUtil.startActivityInApp(this, item.getIntent());
} else {
diff --git a/src/com/android/contacts/interactions/AccountFiltersFragment.java b/src/com/android/contacts/interactions/AccountFiltersFragment.java
new file mode 100644
index 0000000..44a6edf
--- /dev/null
+++ b/src/com/android/contacts/interactions/AccountFiltersFragment.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.contacts.interactions;
+
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.content.Loader;
+import android.os.Bundle;
+
+import com.android.contacts.common.list.ContactListFilter;
+import com.android.contacts.common.util.AccountFilterUtil;
+
+import java.util.List;
+
+/**
+ * Loads account filters.
+ */
+public class AccountFiltersFragment extends Fragment {
+
+ private static final int LOADER_FILTERS = 1;
+
+ /**
+ * Callbacks for hosts of the {@link AccountFiltersFragment}.
+ */
+ public interface AccountFiltersListener {
+
+ /**
+ * Invoked after account filters have been loaded.
+ */
+ void onFiltersLoaded(List<ContactListFilter> groupListItems);
+ }
+
+ private final LoaderManager.LoaderCallbacks<List<ContactListFilter>> mFiltersLoaderListener =
+ new LoaderManager.LoaderCallbacks<List<ContactListFilter>> () {
+ @Override
+ public Loader<List<ContactListFilter>> onCreateLoader(int id, Bundle args) {
+ return new AccountFilterUtil.FilterLoader(getActivity());
+ }
+
+ @Override
+ public void onLoadFinished(
+ Loader<List<ContactListFilter>> loader, List<ContactListFilter> data) {
+ if (mListener != null) {
+ mListener.onFiltersLoaded(data);
+ }
+ }
+
+ public void onLoaderReset(Loader<List<ContactListFilter>> loader) {
+ }
+ };
+
+ private AccountFiltersListener mListener;
+
+ @Override
+ public void onStart() {
+ getLoaderManager().initLoader(LOADER_FILTERS, null, mFiltersLoaderListener);
+ super.onStart();
+ }
+
+ public void setListener(AccountFiltersListener listener) {
+ mListener = listener;
+ }
+}
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 9ea8a1d..7749636 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -61,17 +61,6 @@
private View mSearchProgress;
private TextView mSearchProgressText;
- private class FilterHeaderClickListener implements OnClickListener {
- @Override
- public void onClick(View view) {
- AccountFilterUtil.startAccountFilterActivityForResult(
- DefaultContactBrowseListFragment.this,
- REQUEST_CODE_ACCOUNT_FILTER,
- getFilter());
- }
- }
- private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
-
public DefaultContactBrowseListFragment() {
setPhotoLoaderEnabled(true);
// Don't use a QuickContactBadge. Just use a regular ImageView. Using a QuickContactBadge
@@ -115,7 +104,6 @@
super.onCreateView(inflater, container);
mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container);
- mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
// Create an empty user profile header and hide it for now (it will be visible if the
// contacts list will have no user profile).