summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/contactsfragment/ContactsAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/contactsfragment/ContactsAdapter.java')
-rw-r--r--java/com/android/dialer/contactsfragment/ContactsAdapter.java123
1 files changed, 86 insertions, 37 deletions
diff --git a/java/com/android/dialer/contactsfragment/ContactsAdapter.java b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
index 4692eff5d..13895313f 100644
--- a/java/com/android/dialer/contactsfragment/ContactsAdapter.java
+++ b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
@@ -20,20 +20,37 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.Contacts;
+import android.support.annotation.IntDef;
import android.support.v4.util.ArrayMap;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
-import com.android.contacts.common.ContactPhotoManager;
import com.android.dialer.common.Assert;
+import com.android.dialer.contactphoto.ContactPhotoManager;
+import com.android.dialer.contactsfragment.ContactsFragment.ClickAction;
+import com.android.dialer.contactsfragment.ContactsFragment.Header;
+import com.android.dialer.lettertile.LetterTileDrawable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/** List adapter for the union of all contacts associated with every account on the device. */
-final class ContactsAdapter extends RecyclerView.Adapter<ContactViewHolder> {
+final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+
+ private static final int UNKNOWN_VIEW_TYPE = 0;
+ private static final int ADD_CONTACT_VIEW_TYPE = 1;
+ private static final int CONTACT_VIEW_TYPE = 2;
+
+ /** An Enum for the different row view types shown by this adapter. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({UNKNOWN_VIEW_TYPE, ADD_CONTACT_VIEW_TYPE, CONTACT_VIEW_TYPE})
+ @interface ContactsViewType {}
private final ArrayMap<ContactViewHolder, Integer> holderMap = new ArrayMap<>();
private final Context context;
private final Cursor cursor;
+ private final @Header int header;
+ private final @ClickAction int clickAction;
// List of contact sublist headers
private final String[] headers;
@@ -41,23 +58,44 @@ final class ContactsAdapter extends RecyclerView.Adapter<ContactViewHolder> {
// Number of contacts that correspond to each header in {@code headers}.
private final int[] counts;
- public ContactsAdapter(Context context, Cursor cursor) {
+ ContactsAdapter(
+ Context context, Cursor cursor, @Header int header, @ClickAction int clickAction) {
this.context = context;
this.cursor = cursor;
+ this.header = header;
+ this.clickAction = clickAction;
headers = cursor.getExtras().getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
counts = cursor.getExtras().getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
}
@Override
- public ContactViewHolder onCreateViewHolder(ViewGroup parent, int position) {
- return new ContactViewHolder(
- LayoutInflater.from(context).inflate(R.layout.contact_row, parent, false));
+ public RecyclerView.ViewHolder onCreateViewHolder(
+ ViewGroup parent, @ContactsViewType int viewType) {
+ switch (viewType) {
+ case ADD_CONTACT_VIEW_TYPE:
+ return new AddContactViewHolder(
+ LayoutInflater.from(context).inflate(R.layout.add_contact_row, parent, false));
+ case CONTACT_VIEW_TYPE:
+ return new ContactViewHolder(
+ LayoutInflater.from(context).inflate(R.layout.contact_row, parent, false), clickAction);
+ case UNKNOWN_VIEW_TYPE:
+ default:
+ throw Assert.createIllegalStateFailException("Invalid view type: " + viewType);
+ }
}
@Override
- public void onBindViewHolder(ContactViewHolder contactViewHolder, int position) {
+ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
+ if (viewHolder instanceof AddContactViewHolder) {
+ return;
+ }
+
+ ContactViewHolder contactViewHolder = (ContactViewHolder) viewHolder;
holderMap.put(contactViewHolder, position);
cursor.moveToPosition(position);
+ if (header != Header.NONE) {
+ cursor.moveToPrevious();
+ }
String name = getDisplayName(cursor);
String header = getHeaderString(position);
@@ -70,7 +108,7 @@ final class ContactsAdapter extends RecyclerView.Adapter<ContactViewHolder> {
getPhotoId(cursor),
getPhotoUri(cursor),
name,
- 0);
+ LetterTileDrawable.TYPE_DEFAULT);
String photoDescription =
context.getString(com.android.contacts.common.R.string.description_quick_contact_for, name);
@@ -79,44 +117,48 @@ final class ContactsAdapter extends RecyclerView.Adapter<ContactViewHolder> {
// Always show the view holder's header if it's the first item in the list. Otherwise, compare
// it to the previous element and only show the anchored header if the row elements fall into
// the same sublists.
- if (position == 0) {
- contactViewHolder.bind(header, name, contactUri, true);
- } else {
- boolean showHeader = !header.equals(getHeaderString(position - 1));
- contactViewHolder.bind(header, name, contactUri, showHeader);
- }
+ boolean showHeader = position == 0 || !header.equals(getHeaderString(position - 1));
+ contactViewHolder.bind(header, name, contactUri, showHeader);
}
- public void refreshHeaders() {
- for (ContactViewHolder holder : holderMap.keySet()) {
- onBindViewHolder(holder, holderMap.get(holder));
+ /**
+ * Returns {@link #ADD_CONTACT_VIEW_TYPE} if the adapter was initialized with {@link
+ * Header#ADD_CONTACT} and the position is 0. Otherwise, {@link #CONTACT_VIEW_TYPE}.
+ */
+ @Override
+ public @ContactsViewType int getItemViewType(int position) {
+ if (header != Header.NONE && position == 0) {
+ return ADD_CONTACT_VIEW_TYPE;
}
+ return CONTACT_VIEW_TYPE;
}
@Override
- public int getItemCount() {
- return cursor == null ? 0 : cursor.getCount();
- }
-
- public String getHeader(int position) {
- return getHolderAt(position).getHeader();
- }
-
- public TextView getHeaderView(int position) {
- return getHolderAt(position).getHeaderView();
+ public void onViewRecycled(RecyclerView.ViewHolder contactViewHolder) {
+ super.onViewRecycled(contactViewHolder);
+ if (contactViewHolder instanceof ContactViewHolder) {
+ holderMap.remove(contactViewHolder);
+ }
}
- public void setHeaderVisibility(int position, int visibility) {
- getHolderAt(position).getHeaderView().setVisibility(visibility);
+ void refreshHeaders() {
+ for (ContactViewHolder holder : holderMap.keySet()) {
+ int position = holderMap.get(holder);
+ boolean showHeader =
+ position == 0 || !getHeaderString(position).equals(getHeaderString(position - 1));
+ int visibility = showHeader ? View.VISIBLE : View.INVISIBLE;
+ holder.getHeaderView().setVisibility(visibility);
+ }
}
- private ContactViewHolder getHolderAt(int position) {
- for (ContactViewHolder holder : holderMap.keySet()) {
- if (holderMap.get(holder) == position) {
- return holder;
- }
+ @Override
+ public int getItemCount() {
+ int count = cursor == null || cursor.isClosed() ? 0 : cursor.getCount();
+ // Manually insert the header if one exists.
+ if (header != Header.NONE) {
+ count++;
}
- throw Assert.createIllegalStateFailException("No holder for position: " + position);
+ return count;
}
private static String getDisplayName(Cursor cursor) {
@@ -138,7 +180,14 @@ final class ContactsAdapter extends RecyclerView.Adapter<ContactViewHolder> {
return Contacts.getLookupUri(contactId, lookupKey);
}
- private String getHeaderString(int position) {
+ String getHeaderString(int position) {
+ if (header != Header.NONE) {
+ if (position == 0) {
+ return "+";
+ }
+ position--;
+ }
+
int index = -1;
int sum = 0;
while (sum <= position) {