summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Lee <anwlee@google.com>2015-04-10 18:47:15 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-04-10 18:47:16 +0000
commitf7a478d2e65956d819c8126afa3a68646b2508cb (patch)
treea11f62c1c250a112fe61105a4ac65d3540668447 /src
parentdb31914c54f90df78af387a8e8849bca4a98510d (diff)
parent492cd7371c6d8fddc4de85887a4ed9a89d602767 (diff)
Merge "Replace ListView with RecyclerView in call log."
Diffstat (limited to 'src')
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java56
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java34
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViews.java4
-rw-r--r--src/com/android/dialer/calllog/GroupingListAdapter.java79
4 files changed, 60 insertions, 113 deletions
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 3e8efa0b7..07cd215e9 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.PhoneLookup;
+import android.support.v7.widget.RecyclerView.ViewHolder;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
@@ -225,13 +226,12 @@ public class CallLogAdapter extends GroupingListAdapter
mLoading = loading;
}
- @Override
public boolean isEmpty() {
if (mLoading) {
// We don't want the empty state to show when loading.
return false;
} else {
- return super.isEmpty();
+ return getItemCount() == 0;
}
}
@@ -262,48 +262,19 @@ public class CallLogAdapter extends GroupingListAdapter
}
@Override
- protected View newStandAloneView(Context context, ViewGroup parent) {
- return newChildView(context, parent);
- }
-
- @Override
- protected View newGroupView(Context context, ViewGroup parent) {
- return newChildView(context, parent);
- }
-
- @Override
- protected View newChildView(Context context, ViewGroup parent) {
- LayoutInflater inflater = LayoutInflater.from(context);
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.call_log_list_item, parent, false);
// Get the views to bind to and cache them.
- CallLogListItemViews views = CallLogListItemViews.fromView(context, view);
+ CallLogListItemViews views = CallLogListItemViews.fromView(mContext, view);
view.setTag(views);
// Set text height to false on the TextViews so they don't have extra padding.
views.phoneCallDetailsViews.nameView.setElegantTextHeight(false);
views.phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false);
- return view;
- }
-
- @Override
- protected void bindStandAloneView(View view, Context context, Cursor cursor) {
- bindView(view, cursor, 1);
- }
-
- @Override
- protected void bindChildView(View view, Context context, Cursor cursor) {
- bindView(view, cursor, 1);
- }
-
- @Override
- protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
- boolean expanded) {
- bindView(view, cursor, groupSize);
- }
-
- private void findAndCacheViews(View view) {
+ return (CallLogListItemViews) view.getTag();
}
/**
@@ -312,12 +283,17 @@ public class CallLogAdapter extends GroupingListAdapter
* should not. It invokes cross-process methods and the repeat execution can get costly.
*
* @param callLogItemView the view corresponding to this entry
- * @param c the cursor pointing to the entry in the call log
* @param count the number of entries in the current item, greater than 1 if it is a group
*/
- public void bindView(View callLogItemView, Cursor c, int count) {
- callLogItemView.setAccessibilityDelegate(mAccessibilityDelegate);
- final CallLogListItemViews views = (CallLogListItemViews) callLogItemView.getTag();
+ public void onBindViewHolder(ViewHolder viewHolder, int position) {
+ Cursor c = (Cursor) getItem(position);
+ if (c == null) {
+ return;
+ }
+ int count = getGroupSize(position);
+
+ CallLogListItemViews views = (CallLogListItemViews) viewHolder;
+ views.rootView.setAccessibilityDelegate(mAccessibilityDelegate);
// Default case: an item in the call log.
views.primaryActionView.setVisibility(View.VISIBLE);
@@ -435,7 +411,7 @@ public class CallLogAdapter extends GroupingListAdapter
// Listen for the first draw
if (mViewTreeObserver == null) {
- mViewTreeObserver = callLogItemView.getViewTreeObserver();
+ mViewTreeObserver = views.rootView.getViewTreeObserver();
mViewTreeObserver.addOnPreDrawListener(this);
}
}
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index d69c2ed7e..4f4fc1b94 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -21,8 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.DialogFragment;
+import android.app.Fragment;
import android.app.KeyguardManager;
-import android.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
@@ -34,10 +34,11 @@ import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract;
import android.provider.VoicemailContract.Status;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ListView;
@@ -60,7 +61,7 @@ import java.util.List;
* Displays a list of call log entries. To filter for a particular kind of call
* (all, missed or voicemails), specify it in the constructor.
*/
-public class CallLogFragment extends ListFragment
+public class CallLogFragment extends Fragment
implements CallLogQueryHandler.Listener, CallLogAdapter.OnReportButtonClickListener,
CallLogAdapter.CallFetcher {
private static final String TAG = "CallLogFragment";
@@ -76,6 +77,8 @@ public class CallLogFragment extends ListFragment
private static final String KEY_LOG_LIMIT = "log_limit";
private static final String KEY_DATE_LIMIT = "date_limit";
+ private RecyclerView mRecyclerView;
+ private LinearLayoutManager mLayoutManager;
private CallLogAdapter mAdapter;
private CallLogQueryHandler mCallLogQueryHandler;
private boolean mScrollToTop;
@@ -172,9 +175,6 @@ public class CallLogFragment extends ListFragment
}
String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
- mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this,
- new ContactInfoHelper(getActivity(), currentCountryIso), this);
- setListAdapter(mAdapter);
mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
this, mLogLimit);
mKeyguardManager =
@@ -201,9 +201,8 @@ public class CallLogFragment extends ListFragment
// This will update the state of the "Clear call log" menu item.
getActivity().invalidateOptionsMenu();
- final ListView listView = getListView();
boolean showListView = cursor.getCount() > 0;
- listView.setVisibility(showListView ? View.VISIBLE : View.GONE);
+ mRecyclerView.setVisibility(showListView ? View.VISIBLE : View.GONE);
mEmptyListView.setVisibility(!showListView ? View.VISIBLE : View.GONE);
if (mScrollToTop) {
@@ -213,8 +212,9 @@ public class CallLogFragment extends ListFragment
// will not experience the illusion of downward motion. Instead,
// if we're not already near the top of the list, we instantly jump
// near the top, and animate from there.
- if (listView.getFirstVisiblePosition() > 5) {
- listView.setSelection(5);
+ if (mLayoutManager.findFirstVisibleItemPosition() > 5) {
+ // TODO: Jump to near the top, then begin smooth scroll.
+ mRecyclerView.smoothScrollToPosition(0);
}
// Workaround for framework issue: the smooth-scroll doesn't
// occur if setSelection() is called immediately before.
@@ -224,7 +224,7 @@ public class CallLogFragment extends ListFragment
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
- listView.smoothScrollToPosition(0);
+ mRecyclerView.smoothScrollToPosition(0);
}
});
@@ -269,6 +269,17 @@ public class CallLogFragment extends ListFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
View view = inflater.inflate(R.layout.call_log_fragment, container, false);
+
+ mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
+ mRecyclerView.setHasFixedSize(true);
+ mLayoutManager = new LinearLayoutManager(getActivity());
+ mRecyclerView.setLayoutManager(mLayoutManager);
+
+ String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
+ mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this,
+ new ContactInfoHelper(getActivity(), currentCountryIso), this);
+ mRecyclerView.setAdapter(mAdapter);
+
mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
mStatusMessageView = view.findViewById(R.id.voicemail_status);
mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
@@ -280,7 +291,6 @@ public class CallLogFragment extends ListFragment
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mEmptyListView = view.findViewById(R.id.empty_list_view);
- getListView().setItemsCanFocus(true);
updateEmptyMessage(mCallTypeFilter);
}
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index 9d11a3ab6..f2bed531f 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;
import android.provider.CallLog.Calls;
+import android.support.v7.widget.RecyclerView;
import android.telecom.PhoneAccountHandle;
import android.text.TextUtils;
import android.view.View;
@@ -44,7 +45,7 @@ import com.android.dialer.R;
* is a way of isolating view logic from the CallLogAdapter. We should consider moving that logic
* if the call log list item is eventually represented as a UI component.
*/
-public final class CallLogListItemViews {
+public final class CallLogListItemViews extends RecyclerView.ViewHolder {
/** The root view of the call log list item */
public final View rootView;
/** The quick contact badge for the contact. */
@@ -147,6 +148,7 @@ public final class CallLogListItemViews {
PhoneCallDetailsViews phoneCallDetailsViews,
View callLogEntryView,
TextView dayGroupHeader) {
+ super(rootView);
mContext = context;
this.rootView = rootView;
diff --git a/src/com/android/dialer/calllog/GroupingListAdapter.java b/src/com/android/dialer/calllog/GroupingListAdapter.java
index 78955492e..501e88df0 100644
--- a/src/com/android/dialer/calllog/GroupingListAdapter.java
+++ b/src/com/android/dialer/calllog/GroupingListAdapter.java
@@ -21,6 +21,8 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
@@ -34,7 +36,7 @@ import com.android.contacts.common.testing.NeededForTesting;
* The list has three types of elements: stand-alone, group header and group child. Groups are
* collapsible and collapsed by default. This is used by the call log to group related entries.
*/
-abstract class GroupingListAdapter extends BaseAdapter {
+abstract class GroupingListAdapter extends RecyclerView.Adapter {
private static final int GROUP_METADATA_ARRAY_INITIAL_SIZE = 16;
private static final int GROUP_METADATA_ARRAY_INCREMENT = 128;
@@ -109,11 +111,6 @@ abstract class GroupingListAdapter extends BaseAdapter {
public void onChanged() {
notifyDataSetChanged();
}
-
- @Override
- public void onInvalidated() {
- notifyDataSetInvalidated();
- }
};
public GroupingListAdapter(Context context) {
@@ -127,15 +124,7 @@ abstract class GroupingListAdapter extends BaseAdapter {
*/
protected abstract void addGroups(Cursor cursor);
- protected abstract View newStandAloneView(Context context, ViewGroup parent);
- protected abstract void bindStandAloneView(View view, Context context, Cursor cursor);
-
- protected abstract View newGroupView(Context context, ViewGroup parent);
- protected abstract void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
- boolean expanded);
-
- protected abstract View newChildView(Context context, ViewGroup parent);
- protected abstract void bindChildView(View view, Context context, Cursor cursor);
+ protected abstract void onContentChanged();
/**
* Cache should be reset whenever the cursor changes or groups are expanded or collapsed.
@@ -149,9 +138,6 @@ abstract class GroupingListAdapter extends BaseAdapter {
mPositionCache.clear();
}
- protected void onContentChanged() {
- }
-
public void changeCursor(Cursor cursor) {
if (cursor == mCursor) {
return;
@@ -171,13 +157,10 @@ abstract class GroupingListAdapter extends BaseAdapter {
cursor.registerDataSetObserver(mDataSetObserver);
mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id");
notifyDataSetChanged();
- } else {
- // notify the observers about the lack of a data set
- notifyDataSetInvalidated();
}
-
}
+ @NeededForTesting
public Cursor getCursor() {
return mCursor;
}
@@ -231,7 +214,8 @@ abstract class GroupingListAdapter extends BaseAdapter {
return need;
}
- public int getCount() {
+ @Override
+ public int getItemCount() {
if (mCursor == null) {
return 0;
}
@@ -343,6 +327,7 @@ abstract class GroupingListAdapter extends BaseAdapter {
if (position < listPosition) {
metadata.itemType = ITEM_TYPE_STANDALONE;
metadata.cursorPosition = cursorPosition - (listPosition - position);
+ metadata.childCount = 1;
return;
}
@@ -382,6 +367,7 @@ abstract class GroupingListAdapter extends BaseAdapter {
// The required item is past the last group
metadata.itemType = ITEM_TYPE_STANDALONE;
metadata.cursorPosition = cursorPosition + (position - listPosition);
+ metadata.childCount = 1;
}
/**
@@ -421,12 +407,6 @@ abstract class GroupingListAdapter extends BaseAdapter {
notifyDataSetChanged();
}
- @Override
- public int getViewTypeCount() {
- return 3;
- }
-
- @Override
public int getItemViewType(int position) {
obtainPositionMetadata(mPositionMetadata, position);
return mPositionMetadata.itemType;
@@ -454,37 +434,16 @@ abstract class GroupingListAdapter extends BaseAdapter {
}
}
- public View getView(int position, View convertView, ViewGroup parent) {
- obtainPositionMetadata(mPositionMetadata, position);
- View view = convertView;
- if (view == null) {
- switch (mPositionMetadata.itemType) {
- case ITEM_TYPE_STANDALONE:
- view = newStandAloneView(mContext, parent);
- break;
- case ITEM_TYPE_GROUP_HEADER:
- view = newGroupView(mContext, parent);
- break;
- case ITEM_TYPE_IN_GROUP:
- view = newChildView(mContext, parent);
- break;
- }
- }
-
- mCursor.moveToPosition(mPositionMetadata.cursorPosition);
- switch (mPositionMetadata.itemType) {
- case ITEM_TYPE_STANDALONE:
- bindStandAloneView(view, mContext, mCursor);
- break;
- case ITEM_TYPE_GROUP_HEADER:
- bindGroupView(view, mContext, mCursor, mPositionMetadata.childCount,
- mPositionMetadata.isExpanded);
- break;
- case ITEM_TYPE_IN_GROUP:
- bindChildView(view, mContext, mCursor);
- break;
-
+ /**
+ * Used for setting the cursor without triggering a UI thread update.
+ */
+ @NeededForTesting
+ public void setCursorForTesting(Cursor cursor) {
+ if (cursor != null) {
+ mCursor = cursor;
+ cursor.registerContentObserver(mChangeObserver);
+ cursor.registerDataSetObserver(mDataSetObserver);
+ mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id");
}
- return view;
}
}