Commit 71d6c062 authored by Finnur Thorarinsson's avatar Finnur Thorarinsson Committed by Commit Bot

Contacts Picker: Add Search capability.

Bug: 860467
Change-Id: If72184b571a5d550e321bf8568523a16c9fb35f0
Reviewed-on: https://chromium-review.googlesource.com/1177603
Commit-Queue: Finnur Thorarinsson <finnur@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583687}
parent fa7edddb
......@@ -18,6 +18,15 @@
android:layout_height="wrap_content"
android:layout_gravity="end">
<!-- The ContentDescription for this View gets set in Java -->
<ImageView
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@drawable/ic_search"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
......
......@@ -56,6 +56,22 @@ public class PickerAdapter extends Adapter<ViewHolder> {
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC");
}
/**
* Sets the search query (filter) for the contact list. Filtering is by display name.
* @param query The search term to use.
*/
public void setSearchString(String query) {
String searchString = "%" + query + "%";
String[] selectionArgs = {searchString};
mContactsCursor.close();
mContactsCursor = mCategoryView.getActivity().getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, PROJECTION,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?", selectionArgs,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC");
notifyDataSetChanged();
}
/**
* Fetches all known contacts and their emails.
* @return The contact list as a set.
......
......@@ -13,25 +13,30 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.RoundedIconGenerator;
import org.chromium.chrome.browser.widget.selection.SelectableListLayout;
import org.chromium.chrome.browser.widget.selection.SelectableListToolbar;
import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
import org.chromium.ui.ContactsPickerListener;
import org.chromium.ui.UiUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
/**
* A class for keeping track of common data associated with showing contact details in
* the contacts picker, for example the RecyclerView.
*/
public class PickerCategoryView extends RelativeLayout implements View.OnClickListener {
public class PickerCategoryView extends RelativeLayout
implements View.OnClickListener, SelectionDelegate.SelectionObserver<ContactDetails>,
SelectableListToolbar.SearchDelegate {
// Constants for the RoundedIconGenerator.
private static final int ICON_SIZE_DP = 32;
private static final int ICON_CORNER_RADIUS_DP = 20;
......@@ -67,6 +72,12 @@ public class PickerCategoryView extends RelativeLayout implements View.OnClickLi
// The {@link SelectionDelegate} keeping track of which contacts are selected.
private SelectionDelegate<ContactDetails> mSelectionDelegate;
// The search icon.
private ImageView mSearchButton;
// Keeps track of list of last selected contacts.
List<ContactDetails> mPreviousSelection;
// The Done text button that confirms the selection choice.
private Button mDoneButton;
......@@ -79,6 +90,7 @@ public class PickerCategoryView extends RelativeLayout implements View.OnClickLi
mActivity = (Activity) context;
mSelectionDelegate = new SelectionDelegate<ContactDetails>();
mSelectionDelegate.addObserver(this);
Resources resources = getActivity().getResources();
int iconColor =
......@@ -97,7 +109,10 @@ public class PickerCategoryView extends RelativeLayout implements View.OnClickLi
R.string.contacts_picker_select_contacts, null, 0, 0, R.color.modern_primary_color,
null, false, false);
mToolbar.setNavigationOnClickListener(this);
mToolbar.initializeSearchView(this, R.string.contacts_picker_search, 0);
mSearchButton = (ImageView) mToolbar.findViewById(R.id.search);
mSearchButton.setOnClickListener(this);
mDoneButton = (Button) mToolbar.findViewById(R.id.done);
mDoneButton.setOnClickListener(this);
......@@ -128,6 +143,58 @@ public class PickerCategoryView extends RelativeLayout implements View.OnClickLi
mPickerAdapter.notifyDataSetChanged();
}
private void onStartSearch() {
mDoneButton.setVisibility(GONE);
// Showing the search clears current selection. Save it, so we can restore it after the
// search has completed.
mPreviousSelection = mSelectionDelegate.getSelectedItems();
mSearchButton.setVisibility(GONE);
mToolbar.showSearchView();
}
// SelectableListToolbar.SearchDelegate:
@Override
public void onEndSearch() {
mPickerAdapter.setSearchString("");
mToolbar.showCloseButton();
mToolbar.setNavigationOnClickListener(this);
mDoneButton.setVisibility(VISIBLE);
mSearchButton.setVisibility(VISIBLE);
// Hiding the search view clears the selection. Save it first and restore to the old
// selection, with the new item added during search.
// TODO(finnur): This needs to be revisited after UX is finalized.
HashSet<ContactDetails> selection = new HashSet<>();
for (ContactDetails item : mSelectionDelegate.getSelectedItems()) {
selection.add(item);
}
mToolbar.hideSearchView();
for (ContactDetails item : mPreviousSelection) {
selection.add(item);
}
// TODO(finnur): Do this asynchronously to make the number roll view show the right number.
mSelectionDelegate.setSelectedItems(selection);
}
@Override
public void onSearchTextChanged(String query) {
mPickerAdapter.setSearchString(query);
}
// SelectionDelegate.SelectionObserver:
@Override
public void onSelectionStateChange(List<ContactDetails> selectedItems) {
// Once a selection is made, drop out of search mode. Note: This function is also called
// when entering search mode (with selectedItems then being 0 in size).
if (mToolbar.isSearching() && selectedItems.size() > 0) {
mToolbar.hideSearchView();
}
}
// OnClickListener:
@Override
......@@ -135,6 +202,8 @@ public class PickerCategoryView extends RelativeLayout implements View.OnClickLi
int id = view.getId();
if (id == R.id.done) {
notifyContactsSelected();
} else if (id == R.id.search) {
onStartSearch();
} else {
executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null);
}
......
......@@ -21,6 +21,7 @@ public class SelectionDelegate<E> {
/**
* Observer interface to be notified of selection changes.
* @param <E> The type of the selectable items this delegate interacts with.
*/
public interface SelectionObserver<E> {
/**
......@@ -59,6 +60,15 @@ public class SelectionDelegate<E> {
return isItemSelected(item);
}
/**
* Initializes the selected item list with a new set (clears previous selection).
* @param items The items to set as selected.
*/
public void setSelectedItems(Set<E> items) {
mSelectedItems = items;
notifyObservers();
}
/**
* True if the item is selected. False otherwise.
* @param item The item.
......
......@@ -3401,6 +3401,9 @@ However, you aren’t invisible. Going private doesn’t hide your browsing from
</message>
<!-- Contacts Picker strings -->
<message name="IDS_CONTACTS_PICKER_SEARCH" desc="The hint text for the search box for contacts.">
Search your contacts
</message>
<message name="IDS_CONTACTS_PICKER_SELECT_CONTACTS" desc="The label at the top of the dialog that allows users to select contacts from their device and share the details with a web page.">
Select contacts
</message>
......
26c0c8e6612f7798a1c2648c17f1cba0cb088aa9
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment