From 51f2b28ae6a45f57f94e5c9a66081a10aebc8349 Mon Sep 17 00:00:00 2001 From: zachh Date: Fri, 25 Aug 2017 12:19:07 -0700 Subject: Added partial UI to new call log. UI notes: -Updated view holder to show number and basic secondary text -Updated adapter to divide "Today" and "Older" entries -Photo is just an anonymous avatar for now -Clicking anywhere is a no-op Other things done in this CL: -Plumbed a few more columns through the call log framework -Tweaked some column names in the data model (contract) -Cleaned up some existing tests and added some new ones Screenshot: https://screenshot.googleplex.com/DiMscW47AYb This is the complete spec I am working from: https://screenshot.googleplex.com/XLquTek1oHk Bug: 34672501 Test: existing and new Change-Id: Ice0e538e23e59b7d752f47125a5f9da96bf91430 PiperOrigin-RevId: 166508997 --- .../dialer/calllog/ui/NewCallLogAdapter.java | 126 +++++++++++++++++++-- 1 file changed, 116 insertions(+), 10 deletions(-) (limited to 'java/com/android/dialer/calllog/ui/NewCallLogAdapter.java') diff --git a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java index 4655b0982..b922a6e3b 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java @@ -16,34 +16,140 @@ package com.android.dialer.calllog.ui; import android.database.Cursor; +import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.ViewGroup; +import com.android.dialer.calllogutils.CallLogDates; +import com.android.dialer.common.Assert; +import com.android.dialer.time.Clock; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** {@link RecyclerView.Adapter} for the new call log fragment. */ -final class NewCallLogAdapter extends RecyclerView.Adapter { +final class NewCallLogAdapter extends RecyclerView.Adapter { + + /** IntDef for the different types of rows that can be shown in the call log. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({RowType.HEADER_TODAY, RowType.HEADER_OLDER, RowType.CALL_LOG_ENTRY}) + @interface RowType { + /** Header that displays "Today". */ + int HEADER_TODAY = 1; + /** Header that displays "Older". */ + int HEADER_OLDER = 2; + /** A row representing a call log entry (which could represent one or more calls). */ + int CALL_LOG_ENTRY = 3; + } private final Cursor cursor; + private final Clock clock; - NewCallLogAdapter(Cursor cursor) { + /** Null when the "Today" header should not be displayed. */ + @Nullable private final Integer todayHeaderPosition; + /** Null when the "Older" header should not be displayed. */ + @Nullable private final Integer olderHeaderPosition; + + NewCallLogAdapter(Cursor cursor, Clock clock) { this.cursor = cursor; + this.clock = clock; + + // Calculate header adapter positions by reading cursor. + long currentTimeMillis = clock.currentTimeMillis(); + if (cursor.moveToNext()) { + CoalescedAnnotatedCallLogCursorLoader.Row firstRow = + new CoalescedAnnotatedCallLogCursorLoader.Row(cursor); + if (CallLogDates.isSameDay(currentTimeMillis, firstRow.timestamp())) { + this.todayHeaderPosition = 0; + int adapterPosition = 2; // Accounted for "Today" header and first row. + while (cursor.moveToNext()) { + CoalescedAnnotatedCallLogCursorLoader.Row row = + new CoalescedAnnotatedCallLogCursorLoader.Row(cursor); + if (CallLogDates.isSameDay(currentTimeMillis, row.timestamp())) { + adapterPosition++; + } else { + this.olderHeaderPosition = adapterPosition; + return; + } + } + this.olderHeaderPosition = null; // Didn't find any "Older" rows. + } else { + this.todayHeaderPosition = null; // Didn't find any "Today" rows. + this.olderHeaderPosition = 0; + } + } else { // There are no rows, just need to set these because they are final. + this.todayHeaderPosition = null; + this.olderHeaderPosition = null; + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, @RowType int viewType) { + switch (viewType) { + case RowType.HEADER_TODAY: + case RowType.HEADER_OLDER: + return new HeaderViewHolder( + LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.new_call_log_header, viewGroup, false)); + case RowType.CALL_LOG_ENTRY: + return new NewCallLogViewHolder( + LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.new_call_log_entry, viewGroup, false), + clock); + default: + throw Assert.createUnsupportedOperationFailException("Unsupported view type: " + viewType); + } } @Override - public NewCallLogViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - return new NewCallLogViewHolder( - LayoutInflater.from(viewGroup.getContext()) - .inflate(R.layout.new_call_log_entry, viewGroup, false)); + public void onBindViewHolder(ViewHolder viewHolder, int position) { + if (viewHolder instanceof HeaderViewHolder) { + HeaderViewHolder headerViewHolder = (HeaderViewHolder) viewHolder; + @RowType int viewType = getItemViewType(position); + if (viewType == RowType.HEADER_OLDER) { + headerViewHolder.setHeader(R.string.new_call_log_header_older); + } else if (viewType == RowType.HEADER_TODAY) { + headerViewHolder.setHeader(R.string.new_call_log_header_today); + } else { + throw Assert.createIllegalStateFailException( + "Unexpected view type " + viewType + " at position: " + position); + } + return; + } + NewCallLogViewHolder newCallLogViewHolder = (NewCallLogViewHolder) viewHolder; + int previousHeaders = 0; + if (todayHeaderPosition != null && position > todayHeaderPosition) { + previousHeaders++; + } + if (olderHeaderPosition != null && position > olderHeaderPosition) { + previousHeaders++; + } + cursor.moveToPosition(position - previousHeaders); + newCallLogViewHolder.bind(cursor); } @Override - public void onBindViewHolder(NewCallLogViewHolder viewHolder, int position) { - cursor.moveToPosition(position); - viewHolder.bind(cursor); + @RowType + public int getItemViewType(int position) { + if (todayHeaderPosition != null && position == todayHeaderPosition) { + return RowType.HEADER_TODAY; + } + if (olderHeaderPosition != null && position == olderHeaderPosition) { + return RowType.HEADER_OLDER; + } + return RowType.CALL_LOG_ENTRY; } @Override public int getItemCount() { - return cursor.getCount(); + int numberOfHeaders = 0; + if (todayHeaderPosition != null) { + numberOfHeaders++; + } + if (olderHeaderPosition != null) { + numberOfHeaders++; + } + return cursor.getCount() + numberOfHeaders; } } -- cgit v1.2.3