diff options
Diffstat (limited to 'java/com/android/dialer/contactsfragment/ContactsAdapter.java')
-rw-r--r-- | java/com/android/dialer/contactsfragment/ContactsAdapter.java | 123 |
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) { |