Add multiselect to contact picker
Bug 29502243
Bug 18641067
Change-Id: If5e0c500de752f19589817773c0ee59eb2217da3
diff --git a/res/layout/contact_picker.xml b/res/layout/contact_picker.xml
index 2efe471..faf5563 100644
--- a/res/layout/contact_picker.xml
+++ b/res/layout/contact_picker.xml
@@ -14,9 +14,14 @@
limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/ContactPickerLayout"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_container"
+ android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent" >
+
+ <include
+ layout="@layout/people_activity_toolbar"
+ android:id="@+id/toolbar_parent" />
+
+</LinearLayout>
diff --git a/res/layout/custom_action_bar.xml b/res/layout/custom_action_bar.xml
deleted file mode 100644
index 5b930ea..0000000
--- a/res/layout/custom_action_bar.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<!-- Dimensions are set at runtime in ActionBarAdapter -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dip"
- android:layout_height="0dip" >
-
- <!-- To prevent the search view from getting the initial focus. -->
- <View
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:layout_width="1px"
- android:layout_height="1px" >
- <requestFocus />
- </View>
- <SearchView
- android:id="@+id/search_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:iconifiedByDefault="false"
- android:inputType="textFilter"
- android:theme="@style/ContactPickerSearchTheme" />
-
-</FrameLayout>
diff --git a/res/menu/group_member_picker.xml b/res/menu/group_member_picker.xml
new file mode 100644
index 0000000..ab1fadf
--- /dev/null
+++ b/res/menu/group_member_picker.xml
@@ -0,0 +1,31 @@
+<?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:contacts="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/menu_done"
+ android:icon="@drawable/ic_done_wht_24dp"
+ android:title="@string/menu_addContactsToGroup"
+ contacts:showAsAction="always" />
+
+ <item
+ android:id="@+id/menu_select"
+ android:title="@string/menu_selectForGroup" />
+ contacts:showAsAction="never" />
+
+</menu>
diff --git a/res/menu/search_menu.xml b/res/menu/search_menu.xml
index 355442e..89068d0 100644
--- a/res/menu/search_menu.xml
+++ b/res/menu/search_menu.xml
@@ -13,10 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:contacts="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_search"
android:icon="@drawable/ic_ab_search"
android:title="@string/menu_search"
- android:showAsAction="always" />
+ contacts:showAsAction="always" />
</menu>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index fb0f483..11dc54e 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -15,11 +15,6 @@
-->
<resources>
- <style name="ContactPickerLayout" parent="ContactPickerTheme">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">match_parent</item>
- </style>
-
<style name="DetailActivityTheme" parent="@android:Theme.Dialog">
<item name="android:windowContentOverlay">@null</item>
</style>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 479afd2..e735c58 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -139,6 +139,12 @@
<!-- Menu item to search for contacts to add to the currently selected label. CHAR LIMIT=30] -->
<string name="menu_addToGroup">Add contact</string>
+ <!-- Menu item to select multiple contacts to add to the currently selected label. CHAR LIMIT=30] -->
+ <string name="menu_selectForGroup">Select contacts</string>
+
+ <!-- Menu item to add selected contacts to the currently selected label. CHAR LIMIT=30] -->
+ <string name="menu_addContactsToGroup">Add contacts</string>
+
<!-- Menu item to remove the currently selected contacts from the currently selected label. [CHAR LIMIT=60] -->
<string name="menu_removeFromGroup">Remove from label</string>
@@ -334,8 +340,8 @@
<!-- Toast displayed when contacts are removed from a label. [CHAR LIMIT=50] -->
<string name="groupMembersRemovedToast">Removed contacts</string>
- <!-- Toast displayed when a contact is added to a label. [CHAR LIMIT=50] -->
- <string name="groupMembersAddedToast">Added contact</string>
+ <!-- Toast displayed when one or more contacts is added to a label. [CHAR LIMIT=50] -->
+ <string name="groupMembersAddedToast">Added to label</string>
<!-- Toast displayed when saving a label failed [CHAR LIMIT=70] -->
<string name="groupSavedErrorToast">Couldn\'t save label changes.</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0358caa..5e46c86 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -221,18 +221,6 @@
<item name="titleTextAppearance">@style/ContactsActionBarTitleTextAppCompat</item>
</style>
- <style name="ContactsPickerActionBarStyle" parent="@style/ContactsActionBarStyle">
- <!-- when first loading, don't show title or up button -->
- <item name="android:displayOptions"></item>
- </style>
-
- <style name="ContactPickerSearchTheme" parent="@style/PeopleTheme">
- <item name="android:textColorPrimary">@android:color/white</item>
- <item name="android:textColorHint">?android:textColorHintInverse</item>
- <item name="android:colorControlActivated">?android:textColorHintInverse</item>
- <item name="android:colorControlNormal">@android:color/white</item>
- </style>
-
<!-- Text in the action bar at the top of the screen -->
<style name="ContactsActionBarTitleText"
parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
@@ -276,13 +264,7 @@
<item name="android:listSelector">?android:attr/listChoiceBackgroundIndicator</item>
</style>
- <style name="ContactPickerTheme" parent="@style/PeopleTheme" >
- <item name="android:actionBarStyle">@style/ContactsPickerActionBarStyle</item>
- </style>
-
- <style name="ContactPickerLayout" parent="ContactPickerTheme">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">match_parent</item>
+ <style name="ContactPickerTheme" parent="PeopleActivityTheme" >
</style>
<style name="ContactsPreferencesTheme" parent="@style/PeopleTheme">
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index 3af9c4b..047be6a 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -81,6 +81,7 @@
private boolean mSelectionMode;
private boolean mSearchMode;
+ private boolean mTransparentStatuBar;
private String mQueryString;
private EditText mSearchView;
@@ -314,6 +315,11 @@
return mSelectionMode;
}
+ /** Whether to make the status bar transparent. */
+ public void setTransparentStatuBar(boolean flag) {
+ mTransparentStatuBar = flag;
+ }
+
public void setSearchMode(boolean flag) {
if (mSearchMode != flag) {
mSearchMode = flag;
@@ -517,6 +523,10 @@
final int cabStatusBarColor = mActivity.getResources().getColor(
R.color.contextual_selection_bar_status_bar_color);
mActivity.getWindow().setStatusBarColor(cabStatusBarColor);
+ } else if (!mTransparentStatuBar) {
+ final int normalStatusBarColor = ContextCompat.getColor(
+ mActivity, R.color.primary_color_dark);
+ mActivity.getWindow().setStatusBarColor(normalStatusBarColor);
} else {
mActivity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 17ba765..9885a14 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -16,51 +16,46 @@
package com.android.contacts.activities;
-import android.app.ActionBar;
-import android.app.ActionBar.LayoutParams;
import android.app.Fragment;
import android.content.ActivityNotFoundException;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
+import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.SearchView;
-import android.widget.SearchView.OnCloseListener;
-import android.widget.SearchView.OnQueryTextListener;
import android.widget.Toast;
-import com.android.contacts.ContactsActivity;
+import com.android.contacts.AppCompatContactsActivity;
import com.android.contacts.R;
import com.android.contacts.common.activity.RequestPermissionsActivity;
import com.android.contacts.common.list.ContactEntryListFragment;
-import com.android.contacts.list.GroupMemberPickerFragment;
-import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.contacts.common.list.DirectoryListLoader;
+import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.common.list.PhoneNumberPickerFragment;
+import com.android.contacts.common.util.ViewUtil;
import com.android.contacts.editor.EditorIntents;
import com.android.contacts.list.ContactPickerFragment;
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
-import com.android.contacts.common.list.DirectoryListLoader;
import com.android.contacts.list.EmailAddressPickerFragment;
+import com.android.contacts.list.GroupMemberPickerFragment;
import com.android.contacts.list.JoinContactListFragment;
import com.android.contacts.list.LegacyPhoneNumberPickerFragment;
+import com.android.contacts.list.MultiSelectContactsListFragment;
+import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener;
import com.android.contacts.list.OnContactPickerActionListener;
import com.android.contacts.list.OnEmailAddressPickerActionListener;
-import com.android.contacts.list.UiIntentActions;
-import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
import com.android.contacts.list.OnPostalAddressPickerActionListener;
-import com.android.contacts.common.list.PhoneNumberPickerFragment;
import com.android.contacts.list.PostalAddressPickerFragment;
+import com.android.contacts.list.UiIntentActions;
import java.util.ArrayList;
@@ -68,10 +63,10 @@
* Displays a list of contacts (or phone numbers or postal addresses) for the
* purposes of selecting one.
*/
-public class ContactSelectionActivity extends ContactsActivity
- implements View.OnCreateContextMenuListener, OnQueryTextListener, OnClickListener,
- OnCloseListener, OnFocusChangeListener {
- private static final String TAG = "ContactSelectionActivity";
+public class ContactSelectionActivity extends AppCompatContactsActivity implements
+ View.OnCreateContextMenuListener, ActionBarAdapter.Listener, OnClickListener,
+ OnFocusChangeListener, OnCheckBoxListActionListener {
+ private static final String TAG = "ContactSelection";
private static final String KEY_ACTION_CODE = "actionCode";
private static final String KEY_SEARCH_MODE = "searchMode";
@@ -85,8 +80,9 @@
private boolean mIsSearchSupported;
private ContactsRequest mRequest;
- private SearchView mSearchView;
- private View mSearchViewContainer;
+
+ private ActionBarAdapter mActionBarAdapter;
+ private Toolbar mToolbar;
public ContactSelectionActivity() {
mIntentResolver = new ContactsIntentResolver(this);
@@ -121,8 +117,6 @@
return;
}
- configureActivityTitle();
-
setContentView(R.layout.contact_picker);
if (mActionCode != mRequest.getActionCode()) {
@@ -130,63 +124,46 @@
configureListFragment();
}
- prepareSearchViewAndActionBar();
+ prepareSearchViewAndActionBar(savedState);
+ configureActivityTitle();
}
- private void prepareSearchViewAndActionBar() {
- final ActionBar actionBar = getActionBar();
- mSearchViewContainer = LayoutInflater.from(actionBar.getThemedContext())
- .inflate(R.layout.custom_action_bar, null);
- mSearchView = (SearchView) mSearchViewContainer.findViewById(R.id.search_view);
+ public boolean isSelectionMode() {
+ return mActionBarAdapter.isSelectionMode();
+ }
+
+ public boolean isSearchMode() {
+ return mActionBarAdapter.isSearchMode();
+ }
+
+ private void prepareSearchViewAndActionBar(Bundle savedState) {
+ mToolbar = getView(R.id.toolbar);
+ setSupportActionBar(mToolbar);
+
+ // Add a shadow under the toolbar.
+ ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
+
+ mActionBarAdapter = new ActionBarAdapter(this, this, getSupportActionBar(),
+ /* portraitTabs */ null, /* landscapeTabs */ null, mToolbar,
+ R.string.enter_contact_name);
+ mActionBarAdapter.setShowHomeIcon(true);
+ mActionBarAdapter.setShowHomeAsUp(true);
+ mActionBarAdapter.setTransparentStatuBar(false);
+ mActionBarAdapter.initialize(savedState, mRequest);
// Postal address pickers (and legacy pickers) don't support search, so just show
// "HomeAsUp" button and title.
if (mRequest.getActionCode() == ContactsRequest.ACTION_PICK_POSTAL ||
mRequest.isLegacyCompatibilityMode()) {
- mSearchView.setVisibility(View.GONE);
- if (actionBar != null) {
- actionBar.setDisplayShowHomeEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowTitleEnabled(true);
- }
mIsSearchSupported = false;
- configureSearchMode();
- return;
+ } else {
+ mIsSearchSupported = true;
}
-
- actionBar.setDisplayShowHomeEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
-
- // In order to make the SearchView look like "shown via search menu", we need to
- // manually setup its state. See also DialtactsActivity.java and ActionBarAdapter.java.
- mSearchView.setIconifiedByDefault(true);
- mSearchView.setQueryHint(getString(R.string.hint_findContacts));
- mSearchView.setIconified(false);
- mSearchView.setFocusable(true);
-
- mSearchView.setOnQueryTextListener(this);
- mSearchView.setOnCloseListener(this);
- mSearchView.setOnQueryTextFocusChangeListener(this);
-
- actionBar.setCustomView(mSearchViewContainer,
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- actionBar.setDisplayShowCustomEnabled(true);
-
- mIsSearchSupported = true;
configureSearchMode();
}
private void configureSearchMode() {
- final ActionBar actionBar = getActionBar();
- if (mIsSearchMode) {
- actionBar.setDisplayShowTitleEnabled(false);
- mSearchViewContainer.setVisibility(View.VISIBLE);
- mSearchView.requestFocus();
- } else {
- actionBar.setDisplayShowTitleEnabled(true);
- mSearchViewContainer.setVisibility(View.GONE);
- mSearchView.setQuery(null, true);
- }
+ mActionBarAdapter.setSearchMode(mIsSearchMode);
invalidateOptionsMenu();
}
@@ -215,67 +192,60 @@
private void configureActivityTitle() {
if (!TextUtils.isEmpty(mRequest.getActivityTitle())) {
- setTitle(mRequest.getActivityTitle());
+ getSupportActionBar().setTitle(mRequest.getActivityTitle());
return;
}
-
+ int titleResId = -1;
int actionCode = mRequest.getActionCode();
switch (actionCode) {
case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
- setTitle(R.string.contactInsertOrEditActivityTitle);
+ titleResId = R.string.contactInsertOrEditActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_CONTACT: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
-
case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
- setTitle(R.string.shortcutActivityTitle);
+ titleResId = R.string.shortcutActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_PHONE: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_EMAIL: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
-
case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
- setTitle(R.string.callShortcutActivityTitle);
+ titleResId = R.string.callShortcutActivityTitle;
break;
}
-
case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
- setTitle(R.string.messageShortcutActivityTitle);
+ titleResId = R.string.messageShortcutActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_POSTAL: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
-
case ContactsRequest.ACTION_PICK_JOIN: {
- setTitle(R.string.titleJoinContactDataWith);
+ titleResId = R.string.titleJoinContactDataWith;
break;
}
-
case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: {
- setTitle(R.string.contactPickerActivityTitle);
+ titleResId = R.string.contactPickerActivityTitle;
break;
}
}
+ if (titleResId > 0) {
+ getSupportActionBar().setTitle(titleResId);
+ }
}
/**
@@ -411,11 +381,75 @@
} else if (mListFragment instanceof GroupMemberPickerFragment) {
((GroupMemberPickerFragment) mListFragment).setListener(
new GroupMemberPickerListener());
+ getMultiSelectListFragment().setCheckBoxListListener(this);
} else {
throw new IllegalStateException("Unsupported list fragment type: " + mListFragment);
}
}
+ private MultiSelectContactsListFragment getMultiSelectListFragment() {
+ if (mListFragment instanceof MultiSelectContactsListFragment) {
+ return (MultiSelectContactsListFragment) mListFragment;
+ }
+ return null;
+ }
+
+ @Override
+ public void onAction(int action) {
+ switch (action) {
+ case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
+ mIsSearchMode = true;
+ configureSearchMode();
+ break;
+ case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
+ final String queryString = mActionBarAdapter.getQueryString();
+ mListFragment.setQueryString(queryString, /* delaySelection */ false);
+ break;
+ case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
+ if (getMultiSelectListFragment() != null) {
+ getMultiSelectListFragment().displayCheckBoxes(true);
+ }
+ invalidateOptionsMenu();
+ break;
+ case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
+ mActionBarAdapter.setSearchMode(false);
+ if (getMultiSelectListFragment() != null) {
+ getMultiSelectListFragment().displayCheckBoxes(false);
+ }
+ invalidateOptionsMenu();
+ break;
+ }
+ }
+
+ @Override
+ public void onSelectedTabChanged() {
+ }
+
+ @Override
+ public void onUpButtonPressed() {
+ onBackPressed();
+ }
+
+ @Override
+ public void onStartDisplayingCheckBoxes() {
+ mActionBarAdapter.setSelectionMode(true);
+ }
+
+ @Override
+ public void onSelectedContactIdsChanged() {
+ if (mListFragment instanceof MultiSelectContactsListFragment) {
+ mActionBarAdapter.setSelectionCount(((MultiSelectContactsListFragment) mListFragment)
+ .getSelectedContactIds().size());
+ // Show or hide the multi select "Done" button
+ invalidateOptionsMenu();
+ }
+ }
+
+ @Override
+ public void onStopDisplayingCheckBoxes() {
+ mActionBarAdapter.setSelectionMode(false);
+ }
+
private final class ContactPickerActionListener implements OnContactPickerActionListener {
@Override
public void onCreateNewContactAction() {
@@ -492,6 +526,18 @@
intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, contactId);
returnPickerResult(intent);
}
+
+ @Override
+ public void onGroupMembersSelected(long[] contactIds) {
+ final Intent intent = new Intent();
+ intent.putExtra(UiIntentActions.TARGET_CONTACT_IDS_EXTRA_KEY, contactIds);
+ returnPickerResult(intent);
+ }
+
+ @Override
+ public void onSelectGroupMembers() {
+ mActionBarAdapter.setSelectionMode(true);
+ }
}
private final class PostalAddressPickerActionListener implements
@@ -529,30 +575,11 @@
}
@Override
- public boolean onQueryTextChange(String newText) {
- mListFragment.setQueryString(newText, true);
- return false;
- }
-
- @Override
- public boolean onQueryTextSubmit(String query) {
- return false;
- }
-
- @Override
- public boolean onClose() {
- if (!TextUtils.isEmpty(mSearchView.getQuery())) {
- mSearchView.setQuery(null, true);
- }
- return true;
- }
-
- @Override
public void onFocusChange(View view, boolean hasFocus) {
switch (view.getId()) {
case R.id.search_view: {
if (hasFocus) {
- showInputMethod(mSearchView.findFocus());
+ mActionBarAdapter.setFocusOnSearchView();
}
}
}
@@ -600,16 +627,6 @@
startActivityAndForwardResult(intent);
}
- private void showInputMethod(View view) {
- final InputMethodManager imm = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- if (imm != null) {
- if (!imm.showSoftInput(view, 0)) {
- Log.w(TAG, "Failed to show soft input method.");
- }
- }
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
@@ -631,6 +648,8 @@
if (mIsSearchMode) {
mIsSearchMode = false;
configureSearchMode();
+ } else if (isSelectionMode()) {
+ mActionBarAdapter.setSelectionMode(false);
} else {
super.onBackPressed();
}
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index 7ff5ba0..b25c49a 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -90,15 +90,15 @@
private static class AddGroupMembersAsyncTask extends AsyncTask<Void, Void, Intent> {
private final Context mContext;
- private final long mContactId;
+ private final long[] mContactIds;
private final long mGroupId;
private final String mAccountName;
private final String mAccountType;
- AddGroupMembersAsyncTask(Context context, long contactId, long groupId, String accountName,
- String accountType) {
+ AddGroupMembersAsyncTask(Context context, long[] contactIds, long groupId,
+ String accountName, String accountType) {
mContext = context;
- mContactId = contactId;
+ mContactIds = contactIds;
mGroupId = groupId;
mAccountName = accountName;
mAccountType = accountType;
@@ -124,11 +124,17 @@
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, mAccountType)
.build();
final String[] projection = new String[]{RawContacts._ID};
- final String selection = RawContacts.CONTACT_ID + "=?";
- final String[] selectionArgs = new String[1];
- selectionArgs[0] = Long.toString(mContactId);
+ final StringBuilder selection = new StringBuilder();
+ final String[] selectionArgs = new String[mContactIds.length];
+ for (int i = 0; i < mContactIds.length; i++) {
+ if (i > 0) {
+ selection.append(" OR ");
+ }
+ selection.append(RawContacts.CONTACT_ID).append("=?");
+ selectionArgs[i] = Long.toString(mContactIds[i]);
+ }
final Cursor cursor = mContext.getContentResolver().query(
- rawContactUri, projection, selection, selectionArgs, null, null);
+ rawContactUri, projection, selection.toString(), selectionArgs, null, null);
final long[] rawContactIds = new long[cursor.getCount()];
try {
int i = 0;
@@ -473,9 +479,17 @@
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RESULT_GROUP_ADD_MEMBER && resultCode == RESULT_OK && data != null) {
- final long contactId = data.getLongExtra(
- UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
- new AddGroupMembersAsyncTask(this, contactId, mGroupMetadata.groupId,
+ long[] contactIds = data.getLongArrayExtra(
+ UiIntentActions.TARGET_CONTACT_IDS_EXTRA_KEY);
+ if (contactIds == null) {
+ final long contactId = data.getLongExtra(
+ UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
+ if (contactId > -1) {
+ contactIds = new long[1];
+ contactIds[0] = contactId;
+ }
+ }
+ new AddGroupMembersAsyncTask(this, contactIds, mGroupMetadata.groupId,
mGroupMetadata.accountName, mGroupMetadata.accountType)
.execute();
}
diff --git a/src/com/android/contacts/list/GroupMemberPickerFragment.java b/src/com/android/contacts/list/GroupMemberPickerFragment.java
index d7ad9ed..a90ccbe 100644
--- a/src/com/android/contacts/list/GroupMemberPickerFragment.java
+++ b/src/com/android/contacts/list/GroupMemberPickerFragment.java
@@ -15,17 +15,21 @@
*/
package com.android.contacts.list;
+import android.app.Activity;
import android.content.Loader;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import com.android.contacts.activities.ContactSelectionActivity;
import com.android.contacts.common.R;
-import com.android.contacts.common.list.ContactEntryListFragment;
import com.android.contacts.common.list.ContactListAdapter.ContactQuery;
import com.android.contacts.common.list.ContactListFilter;
import com.android.contacts.common.list.DefaultContactListAdapter;
@@ -36,7 +40,7 @@
* Fragment containing raw contacts for a specified account that are not already in a group.
*/
public class GroupMemberPickerFragment extends
- ContactEntryListFragment<DefaultContactListAdapter> {
+ MultiSelectContactsListFragment<DefaultContactListAdapter> {
public static final String TAG = "GroupMemberPicker";
@@ -55,6 +59,12 @@
/** Invoked when a potential group member is selected. */
void onGroupMemberClicked(long contactId);
+
+ /** Invoked when multiple potential group members are selected. */
+ void onGroupMembersSelected(long[] contactIds);
+
+ /** Invoked when user has initiated multiple selection mode. */
+ void onSelectGroupMembers();
}
/** Filters out raw contacts that are already in the group. */
@@ -213,6 +223,10 @@
@Override
protected void onItemClick(int position, long id) {
+ if (getAdapter().isDisplayingCheckBoxes()) {
+ super.onItemClick(position, id);
+ return;
+ }
if (mListener != null) {
final long contactId = getAdapter().getContactId(position);
if (contactId > 0) {
@@ -220,4 +234,65 @@
}
}
}
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ super.onCreateOptionsMenu(menu, menuInflater);
+ menuInflater.inflate(R.menu.group_member_picker, menu);
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ final ContactSelectionActivity activity = getContactSelectionActivity();
+ final boolean isSearchMode = activity == null ? false : activity.isSearchMode();
+ final boolean isSelectionMode = activity == null ? false : activity.isSelectionMode();
+
+ // Added in ContactSelectionActivity but we must account for selection mode
+ setVisible(menu, R.id.menu_search, !isSearchMode && !isSelectionMode);
+
+ setVisible(menu, R.id.menu_done, !isSearchMode && isSelectionMode &&
+ getAdapter().getSelectedContactIds().size() > 0);
+ setVisible(menu, R.id.menu_select, !isSearchMode && !isSelectionMode);
+ }
+
+ private ContactSelectionActivity getContactSelectionActivity() {
+ final Activity activity = getActivity();
+ if (activity != null && activity instanceof ContactSelectionActivity) {
+ return (ContactSelectionActivity) activity;
+ }
+ return null;
+ }
+
+ private static void setVisible(Menu menu, int id, boolean visible) {
+ final MenuItem menuItem = menu.findItem(id);
+ if (menuItem != null) {
+ menuItem.setVisible(visible);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home: {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.onBackPressed();
+ }
+ return true;
+ }
+ case R.id.menu_done: {
+ if (mListener != null) {
+ mListener.onGroupMembersSelected(getAdapter().getSelectedContactIdsArray());
+ }
+ return true;
+ }
+ case R.id.menu_select: {
+ if (mListener != null) {
+ mListener.onSelectGroupMembers();
+ }
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/src/com/android/contacts/list/UiIntentActions.java b/src/com/android/contacts/list/UiIntentActions.java
index 9552942..39d5007 100644
--- a/src/com/android/contacts/list/UiIntentActions.java
+++ b/src/com/android/contacts/list/UiIntentActions.java
@@ -123,4 +123,7 @@
*/
public static final String TARGET_CONTACT_ID_EXTRA_KEY
= "com.android.contacts.action.CONTACT_ID";
+
+ public static final String TARGET_CONTACT_IDS_EXTRA_KEY
+ = "com.android.contacts.action.CONTACT_IDS";
}
\ No newline at end of file