summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcalderwoodra <calderwoodra@google.com>2017-08-22 11:34:13 -0700
committerEric Erfanian <erfanian@google.com>2017-08-30 14:27:05 -0700
commit429a136f054915dc3f94121d31fcff434ff78430 (patch)
treef5a18c70313aa6831ea591508094fa13cad8a24f
parent1af455b1bcadf44974373956972d227c8b41a11e (diff)
Updated ContactsFragment to use composition.
The following features are now configureable in ContactsFragment: - Presence of the "Create new contact" row at position 0 - The on click action when a user clicks on a row in contacts This change is being made so that this fragment can be reused in the add favorite screen in the new favorites fragment. For more context: https://docs.google.com/document/d/1lCjOgeYQXolrHW32Bgl-Vty_aIalQog_rog-EaO1bMA/edit#heading=h.1qre30w9h49i Bug: 36841782 Test: existing, updated PiperOrigin-RevId: 166089143 Change-Id: I567f4efb9c738f4fc629523e118e3cf116bf4ace
-rw-r--r--java/com/android/dialer/app/list/DialtactsPagerAdapter.java5
-rw-r--r--java/com/android/dialer/contactsfragment/ContactViewHolder.java31
-rw-r--r--java/com/android/dialer/contactsfragment/ContactsAdapter.java45
-rw-r--r--java/com/android/dialer/contactsfragment/ContactsFragment.java65
4 files changed, 125 insertions, 21 deletions
diff --git a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java
index 822aa789f..d9cb0c1f6 100644
--- a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java
+++ b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java
@@ -31,6 +31,8 @@ import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.contactsfragment.ContactsFragment;
+import com.android.dialer.contactsfragment.ContactsFragment.ClickAction;
+import com.android.dialer.contactsfragment.ContactsFragment.Header;
import com.android.dialer.database.CallLogQueryHandler;
import com.android.dialer.speeddial.SpeedDialFragment;
import com.android.dialer.util.ViewUtil;
@@ -120,7 +122,8 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter {
case TAB_INDEX_ALL_CONTACTS:
if (useNewContactsTab) {
if (contactsFragment == null) {
- contactsFragment = new ContactsFragment();
+ contactsFragment =
+ ContactsFragment.newInstance(Header.ADD_CONTACT, ClickAction.OPEN_CONTACT_CARD);
}
return contactsFragment;
} else {
diff --git a/java/com/android/dialer/contactsfragment/ContactViewHolder.java b/java/com/android/dialer/contactsfragment/ContactViewHolder.java
index 586e22aab..0597c2a7e 100644
--- a/java/com/android/dialer/contactsfragment/ContactViewHolder.java
+++ b/java/com/android/dialer/contactsfragment/ContactViewHolder.java
@@ -26,6 +26,7 @@ import android.view.View.OnClickListener;
import android.widget.QuickContactBadge;
import android.widget.TextView;
import com.android.dialer.common.Assert;
+import com.android.dialer.contactsfragment.ContactsFragment.ClickAction;
import com.android.dialer.logging.InteractionEvent;
import com.android.dialer.logging.Logger;
@@ -36,17 +37,20 @@ final class ContactViewHolder extends RecyclerView.ViewHolder implements OnClick
private final TextView name;
private final QuickContactBadge photo;
private final Context context;
+ private final @ClickAction int clickAction;
private String headerText;
private Uri contactUri;
- public ContactViewHolder(View itemView) {
+ ContactViewHolder(View itemView, @ClickAction int clickAction) {
super(itemView);
+ Assert.checkArgument(clickAction != ClickAction.INVALID, "Invalid click action.");
context = itemView.getContext();
itemView.findViewById(R.id.click_target).setOnClickListener(this);
- header = (TextView) itemView.findViewById(R.id.header);
- name = (TextView) itemView.findViewById(R.id.contact_name);
- photo = (QuickContactBadge) itemView.findViewById(R.id.photo);
+ header = itemView.findViewById(R.id.header);
+ name = itemView.findViewById(R.id.contact_name);
+ photo = itemView.findViewById(R.id.photo);
+ this.clickAction = clickAction;
}
/**
@@ -85,9 +89,20 @@ final class ContactViewHolder extends RecyclerView.ViewHolder implements OnClick
@Override
public void onClick(View v) {
- Logger.get(context)
- .logInteraction(InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CONTACTS_FRAGMENT_ITEM);
- QuickContact.showQuickContact(
- photo.getContext(), photo, contactUri, QuickContact.MODE_LARGE, null /* excludeMimes */);
+ switch (clickAction) {
+ case ClickAction.OPEN_CONTACT_CARD:
+ Logger.get(context)
+ .logInteraction(InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CONTACTS_FRAGMENT_ITEM);
+ QuickContact.showQuickContact(
+ photo.getContext(),
+ photo,
+ contactUri,
+ QuickContact.MODE_LARGE,
+ null /* excludeMimes */);
+ break;
+ case ClickAction.INVALID:
+ default:
+ throw Assert.createIllegalStateFailException("Invalid click action.");
+ }
}
}
diff --git a/java/com/android/dialer/contactsfragment/ContactsAdapter.java b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
index 1bd8e343a..13895313f 100644
--- a/java/com/android/dialer/contactsfragment/ContactsAdapter.java
+++ b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
@@ -28,6 +28,8 @@ import android.view.View;
import android.view.ViewGroup;
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;
@@ -47,6 +49,8 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
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;
@@ -54,9 +58,12 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
// Number of contacts that correspond to each header in {@code headers}.
private final int[] counts;
- 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);
}
@@ -70,7 +77,7 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
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));
+ LayoutInflater.from(context).inflate(R.layout.contact_row, parent, false), clickAction);
case UNKNOWN_VIEW_TYPE:
default:
throw Assert.createIllegalStateFailException("Invalid view type: " + viewType);
@@ -85,8 +92,10 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
ContactViewHolder contactViewHolder = (ContactViewHolder) viewHolder;
holderMap.put(contactViewHolder, position);
- // Cursor should be offset by 1 because of add contact row
- cursor.moveToPosition(position - 1);
+ cursor.moveToPosition(position);
+ if (header != Header.NONE) {
+ cursor.moveToPrevious();
+ }
String name = getDisplayName(cursor);
String header = getHeaderString(position);
@@ -112,9 +121,16 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
contactViewHolder.bind(header, name, contactUri, showHeader);
}
+ /**
+ * 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) {
- return position == 0 ? ADD_CONTACT_VIEW_TYPE : CONTACT_VIEW_TYPE;
+ if (header != Header.NONE && position == 0) {
+ return ADD_CONTACT_VIEW_TYPE;
+ }
+ return CONTACT_VIEW_TYPE;
}
@Override
@@ -125,7 +141,7 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
}
}
- public void refreshHeaders() {
+ void refreshHeaders() {
for (ContactViewHolder holder : holderMap.keySet()) {
int position = holderMap.get(holder);
boolean showHeader =
@@ -137,7 +153,12 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
@Override
public int getItemCount() {
- return (cursor == null || cursor.isClosed() ? 0 : cursor.getCount()) + 1; // add contact
+ int count = cursor == null || cursor.isClosed() ? 0 : cursor.getCount();
+ // Manually insert the header if one exists.
+ if (header != Header.NONE) {
+ count++;
+ }
+ return count;
}
private static String getDisplayName(Cursor cursor) {
@@ -159,11 +180,13 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
return Contacts.getLookupUri(contactId, lookupKey);
}
- public String getHeaderString(int position) {
- if (position == 0) {
- return "+";
+ String getHeaderString(int position) {
+ if (header != Header.NONE) {
+ if (position == 0) {
+ return "+";
+ }
+ position--;
}
- position--;
int index = -1;
int sum = 0;
diff --git a/java/com/android/dialer/contactsfragment/ContactsFragment.java b/java/com/android/dialer/contactsfragment/ContactsFragment.java
index 50c9fe82c..86ac834fd 100644
--- a/java/com/android/dialer/contactsfragment/ContactsFragment.java
+++ b/java/com/android/dialer/contactsfragment/ContactsFragment.java
@@ -23,6 +23,7 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
+import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v13.app.FragmentCompat;
import android.support.v7.widget.LinearLayoutManager;
@@ -44,6 +45,8 @@ import com.android.dialer.util.IntentUtil;
import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.widget.EmptyContentView;
import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/** Fragment containing a list of all contacts. */
@@ -53,8 +56,31 @@ public class ContactsFragment extends Fragment
OnEmptyViewActionButtonClickedListener,
ChangeListener {
+ /** IntDef to define the OnClick action for contact rows. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ClickAction.INVALID, ClickAction.OPEN_CONTACT_CARD})
+ public @interface ClickAction {
+ int INVALID = 0;
+ /** Open contact card on click. */
+ int OPEN_CONTACT_CARD = 1;
+ }
+
+ /** An enum for the different types of headers that be inserted at position 0 in the list. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ ContactsFragment.Header.NONE,
+ ContactsFragment.Header.ADD_CONTACT})
+ public @interface Header {
+ int NONE = 0;
+ /** Header that allows the user to add a new contact. */
+ int ADD_CONTACT = 1;
+ }
+
public static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1;
+ private static final String EXTRA_HEADER = "extra_header";
+ private static final String EXTRA_CLICK_ACTION = "extra_click_action";
+
private FastScroller fastScroller;
private TextView anchoredHeader;
private RecyclerView recyclerView;
@@ -63,12 +89,49 @@ public class ContactsFragment extends Fragment
private EmptyContentView emptyContentView;
private ContactsPreferences contactsPrefs;
+ private @Header int header;
+ private @ClickAction int clickAction;
+
+ /**
+ * Used to get a configured instance of ContactsFragment.
+ *
+ * <p>Current example of this fragment are the contacts tab and in creating a new favorite
+ * contact. For example, the contacts tab we use:
+ *
+ * <ul>
+ * <li>{@link Header#ADD_CONTACT} to insert a header that allows users to add a contact
+ * <li>{@link ClickAction#OPEN_CONTACT_CARD} to open contact cards on click
+ * </ul>
+ *
+ * And for the add favorite contact screen we might use:
+ *
+ * <ul>
+ * <li>{@link Header#NONE} so that all rows are contacts (i.e. no header inserted)
+ * <li>{@link ClickAction#SET_RESULT_AND_FINISH} to send a selected contact to the previous
+ * activity.
+ * </ul>
+ *
+ * @param header determines the type of header inserted at position 0 in the contacts list
+ * @param clickAction defines the on click actions on rows that represent contacts
+ */
+ public static ContactsFragment newInstance(@Header int header, @ClickAction int clickAction) {
+ Assert.checkArgument(clickAction != ClickAction.INVALID, "Invalid click action");
+ ContactsFragment fragment = new ContactsFragment();
+ Bundle args = new Bundle();
+ args.putInt(EXTRA_HEADER, header);
+ args.putInt(EXTRA_CLICK_ACTION, clickAction);
+ fragment.setArguments(args);
+ return fragment;
+ }
+ @SuppressWarnings("WrongConstant")
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
contactsPrefs = new ContactsPreferences(getContext());
contactsPrefs.registerChangeListener(this);
+ header = getArguments().getInt(EXTRA_HEADER);
+ clickAction = getArguments().getInt(EXTRA_CLICK_ACTION);
}
@Nullable
@@ -126,7 +189,7 @@ public class ContactsFragment extends Fragment
} else {
emptyContentView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
- adapter = new ContactsAdapter(getContext(), cursor);
+ adapter = new ContactsAdapter(getContext(), cursor, header, clickAction);
manager =
new LinearLayoutManager(getContext()) {
@Override