Switch favorites screen to grid layout
* Add logic to PhoneFavoritesTileAdapter so that it now supports an
unlimited number of tiled rows.
* Tiles now have a configurable height to width ratio.
* Fix animations so that tiles moving up and down rows appear to animate
in from the correct direction. Tiles moving to the row above should animate
in from right to left. Tiles moving to the row below should animate in from
left to right.
* Update the number of columns in the grid to 2.
* Update layout of individual tiles to match redlines from UX.
* Tweak font sizes for tiles
* No longer truncate names in tiles
* Tiles have a 2-3 height to width ratio
* Update assets and layout for favorite and more info icons
* Add content description for the favorite button
* Add tests for PhoneFavoritesTileAdapter
Change-Id: I50b298f0941698985d281f13e6a87c5a9b613efa
diff --git a/res/drawable-hdpi/ic_contact_info.png b/res/drawable-hdpi/ic_contact_info.png
deleted file mode 100644
index 9c23000..0000000
--- a/res/drawable-hdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_marked_as_fav.png b/res/drawable-hdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 8a138c4..0000000
--- a/res/drawable-hdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/overflow_thumbnail.png b/res/drawable-hdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..57db353
--- /dev/null
+++ b/res/drawable-hdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-hdpi/star_thumbnail.png b/res/drawable-hdpi/star_thumbnail.png
new file mode 100644
index 0000000..1d4d5e1
--- /dev/null
+++ b/res/drawable-hdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_info.png b/res/drawable-mdpi/ic_contact_info.png
deleted file mode 100644
index 5d35ec5..0000000
--- a/res/drawable-mdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_marked_as_fav.png b/res/drawable-mdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index ee1b5ec..0000000
--- a/res/drawable-mdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/overflow_thumbnail.png b/res/drawable-mdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..c699374
--- /dev/null
+++ b/res/drawable-mdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-mdpi/star_thumbnail.png b/res/drawable-mdpi/star_thumbnail.png
new file mode 100644
index 0000000..7b96272
--- /dev/null
+++ b/res/drawable-mdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_info.png b/res/drawable-xhdpi/ic_contact_info.png
deleted file mode 100644
index 88d367b..0000000
--- a/res/drawable-xhdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_marked_as_fav.png b/res/drawable-xhdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 372747a..0000000
--- a/res/drawable-xhdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/overflow_thumbnail.png b/res/drawable-xhdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..e538b98
--- /dev/null
+++ b/res/drawable-xhdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-xhdpi/star_thumbnail.png b/res/drawable-xhdpi/star_thumbnail.png
new file mode 100644
index 0000000..a71262f
--- /dev/null
+++ b/res/drawable-xhdpi/star_thumbnail.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_contact_info.png b/res/drawable-xxhdpi/ic_contact_info.png
deleted file mode 100644
index e5d2939..0000000
--- a/res/drawable-xxhdpi/ic_contact_info.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_star_marked_as_fav.png b/res/drawable-xxhdpi/ic_star_marked_as_fav.png
deleted file mode 100644
index 3eeff4c..0000000
--- a/res/drawable-xxhdpi/ic_star_marked_as_fav.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/overflow_thumbnail.png b/res/drawable-xxhdpi/overflow_thumbnail.png
new file mode 100644
index 0000000..7f3f733
--- /dev/null
+++ b/res/drawable-xxhdpi/overflow_thumbnail.png
Binary files differ
diff --git a/res/drawable-xxhdpi/star_thumbnail.png b/res/drawable-xxhdpi/star_thumbnail.png
new file mode 100644
index 0000000..5f13fec
--- /dev/null
+++ b/res/drawable-xxhdpi/star_thumbnail.png
Binary files differ
diff --git a/res/layout/phone_favorite_regular_row_view.xml b/res/layout/phone_favorite_regular_row_view.xml
index 012c9be..0d131f6 100644
--- a/res/layout/phone_favorite_regular_row_view.xml
+++ b/res/layout/phone_favorite_regular_row_view.xml
@@ -75,7 +75,7 @@
android:layout_marginRight="7dip"
android:layout_marginEnd="7dip"
android:layout_marginBottom="7dip"
- android:src="@drawable/ic_star_marked_as_fav"
+ android:src="@drawable/star_thumbnail"
android:visibility="gone" />
</RelativeLayout>
diff --git a/res/layout/phone_favorite_tile_view.xml b/res/layout/phone_favorite_tile_view.xml
index 8806d39..c4ad780 100644
--- a/res/layout/phone_favorite_tile_view.xml
+++ b/res/layout/phone_favorite_tile_view.xml
@@ -46,7 +46,7 @@
android:paddingRight="@dimen/contact_tile_info_button_height_and_width"
android:paddingStart="8dp"
android:paddingEnd="@dimen/contact_tile_info_button_height_and_width"
- android:paddingBottom="4dp"
+ android:paddingBottom="12dp"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
<TextView
@@ -57,7 +57,7 @@
android:textColor="@color/contact_tile_name_color"
android:fontFamily="sans-serif"
android:singleLine="true"
- android:textSize="16sp"
+ android:textSize="15sp"
android:fadingEdge="horizontal"
android:fadingEdgeLength="3dip"
android:ellipsize="marquee"
@@ -70,7 +70,7 @@
android:textColor="@color/contact_tile_name_color"
android:fontFamily="sans-serif"
android:singleLine="true"
- android:textSize="12sp"
+ android:textSize="11sp"
android:paddingBottom="2dp"
android:fadingEdge="horizontal"
android:fadingEdgeLength="3dip"
@@ -90,35 +90,37 @@
android:background="?android:attr/selectableItemBackground"
android:layout_height="@dimen/contact_tile_info_button_height_and_width"
android:layout_width="@dimen/contact_tile_info_button_height_and_width"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:layout_alignParentBottom="true"
+ android:paddingLeft="2dp"
+ android:paddingRight="2dp"
+ android:paddingStart="2dp"
+ android:paddingEnd="2dp"
+ android:paddingTop="2dp"
+ android:paddingBottom="2dp"
+ android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
- android:src="@drawable/ic_star_marked_as_fav"
+ android:src="@drawable/star_thumbnail"
android:scaleType="center"
+ android:contentDescription="@string/description_view_contact_detail"
android:visibility="gone" />
<ImageButton
android:id="@id/contact_tile_secondary_button"
- android:src="@drawable/ic_contact_info"
+ android:src="@drawable/overflow_thumbnail"
android:background="?android:attr/selectableItemBackground"
android:layout_height="@dimen/contact_tile_info_button_height_and_width"
android:layout_width="@dimen/contact_tile_info_button_height_and_width"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:layout_alignParentBottom="true"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
+ android:scaleType="center"
android:contentDescription="@string/description_view_contact_detail" />
</RelativeLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a8ddf2b..b2d4bc5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -63,7 +63,7 @@
<color name="searchbox_text_color">#d3d3d3</color>
<!-- Color of the contact name in favorite tiles -->
- <color name="contact_tile_name_color">#f0f0f0</color>
+ <color name="contact_tile_name_color">#ffffff</color>
<!-- Undo dialogue color -->
<color name="undo_dialogue_text_color">#4d4d4d</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e84b18a..9426987 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -70,10 +70,11 @@
<dimen name="fake_menu_button_min_width">56dp</dimen>
<!-- Favorites tile and recent call log padding -->
- <dimen name="contact_tile_divider_padding">3dp</dimen>
+ <dimen name="contact_tile_divider_width">12dp</dimen>
<dimen name="contact_tile_info_button_height_and_width">36dp</dimen>
- <dimen name="favorites_row_top_padding">8dp</dimen>
- <dimen name="favorites_row_bottom_padding">8dp</dimen>
+ <item name="contact_tile_height_to_width_ratio" type="dimen">67%</item>
+ <dimen name="favorites_row_top_padding">6dp</dimen>
+ <dimen name="favorites_row_bottom_padding">6dp</dimen>
<dimen name="favorites_row_start_padding">8dp</dimen>
<dimen name="favorites_row_end_padding">8dp</dimen>
<dimen name="favorites_row_undo_text_side_padding">32dp</dimen>
diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java
index 2791f15..027674a 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -17,9 +17,7 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
@@ -36,9 +34,9 @@
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
@@ -55,10 +53,10 @@
import com.android.contacts.common.list.ContactTileView;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
-import com.android.dialer.calllog.CallLogQuery;
-import com.android.dialer.calllog.ContactInfoHelper;
import com.android.dialer.calllog.CallLogAdapter;
+import com.android.dialer.calllog.CallLogQuery;
import com.android.dialer.calllog.CallLogQueryHandler;
+import com.android.dialer.calllog.ContactInfoHelper;
import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow;
import com.android.dialerbind.ObjectFactory;
@@ -238,8 +236,8 @@
// that will be available on onCreateView().
mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener,
this,
- getResources().getInteger(R.integer.contact_tile_column_count_in_favorites_new),
- 1);
+ getResources().getInteger(R.integer.contact_tile_column_count_in_favorites),
+ PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity));
}
@@ -424,7 +422,10 @@
}
/**
- * Saves the current view offsets into memory
+ * Cache the current view offsets into memory. Once a relayout of views in the ListView
+ * has happened due to a dataset change, the cached offsets are used to create animations
+ * that slide views from their previous positions to their new ones, to give the appearance
+ * that the views are sliding into their new positions.
*/
@SuppressWarnings("unchecked")
private void saveOffsets(int removedItemHeight) {
@@ -440,7 +441,7 @@
if (itemViewType == PhoneFavoritesTileAdapter.ViewTypes.TOP) {
// This is a tiled row, so save horizontal offsets instead
saveHorizontalOffsets((ContactTileRow) child, (ArrayList<ContactEntry>)
- mAdapter.getItem(position));
+ mAdapter.getItem(position), position);
}
if (DEBUG) {
Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: "
@@ -452,7 +453,13 @@
mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight);
}
- private void saveHorizontalOffsets(ContactTileRow row, ArrayList<ContactEntry> list) {
+ /**
+ * Saves the horizontal offsets for contacts that are displayed as tiles in a row. Saving
+ * these offsets allow us to animate tiles sliding left and right within the same row.
+ * See {@link #saveOffsets(int removedItemHeight)}
+ */
+ private void saveHorizontalOffsets(ContactTileRow row, ArrayList<ContactEntry> list,
+ int currentRowIndex) {
for (int i = 0; i < list.size() && i < row.getChildCount(); i++) {
final View child = row.getChildAt(i);
if (child == null) {
@@ -464,6 +471,7 @@
Log.d(TAG, "Saving itemId: " + itemId + " for tileview child " + i + " Left: "
+ child.getTop());
}
+ mItemIdTopMap.put(itemId, currentRowIndex);
mItemIdLeftMap.put(itemId, child.getLeft());
}
}
@@ -472,7 +480,7 @@
* Performs a animations for a row of tiles
*/
private void performHorizontalAnimations(ContactTileRow row, ArrayList<ContactEntry> list,
- long[] idsInPlace) {
+ long[] idsInPlace, int currentRow) {
if (mItemIdLeftMap.isEmpty()) {
return;
}
@@ -490,6 +498,26 @@
} else {
Integer startLeft = mItemIdLeftMap.get(itemId);
int left = child.getLeft();
+
+ Integer startRow = mItemIdTopMap.get(itemId);
+
+ if (startRow != null) {
+ if (startRow > currentRow) {
+ // Item has shifted upwards to the previous row.
+ // It should now animate in from right to left.
+ startLeft = left + child.getWidth();
+ } else if (startRow < currentRow) {
+ // Item has shifted downwards to the next row.
+ // It should now animate in from left to right.
+ startLeft = left - child.getWidth();
+ }
+
+ // If the item hasn't shifted rows (startRow == currentRow), it either remains
+ // in the same position or has shifted left or right within its current row.
+ // Either way, startLeft has already been correctly saved and retrieved from
+ // mItemIdTopMap.
+ }
+
if (startLeft != null) {
if (startLeft != left) {
int delta = startLeft - left;
@@ -545,7 +573,8 @@
child instanceof ContactTileRow) {
// This is a tiled row, so perform horizontal animations instead
performHorizontalAnimations((ContactTileRow) child, (
- ArrayList<ContactEntry>) mAdapter.getItem(position), idsInPlace);
+ ArrayList<ContactEntry>) mAdapter.getItem(position), idsInPlace,
+ position);
}
final long itemId = mAdapter.getItemId(position);
diff --git a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
index 85e7216..e855c88 100644
--- a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
+++ b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java
@@ -36,10 +36,6 @@
private static final String TAG = PhoneFavoriteSquareTileView.class.getSimpleName();
private ImageButton mSecondaryButton;
- // TODO: Use a more expansive name token separator if needed. For now it should be fine to
- // not split by dashes, underscore etc.
- private static final Pattern NAME_TOKEN_SEPARATOR_PATTERN = Pattern.compile("\\s+");
-
public PhoneFavoriteSquareTileView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -63,14 +59,6 @@
}
@Override
- protected String getNameForView(String name) {
- if (TextUtils.isEmpty(name)) return name;
- final String[] tokens = NAME_TOKEN_SEPARATOR_PATTERN.split(name, 2);
- if (tokens.length < 1) return name;
- return tokens[0];
- }
-
- @Override
public void loadFromContact(ContactEntry entry) {
super.loadFromContact(entry);
if (entry != null) {
diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
index a85fc6a..dff68b2 100644
--- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
@@ -15,7 +15,9 @@
*/
package com.android.dialer.list;
-import android.animation.ObjectAnimator;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ComparisonChain;
+
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -44,9 +46,6 @@
import com.android.dialer.list.SwipeHelper.OnItemGestureListener;
import com.android.dialer.list.SwipeHelper.SwipeHelperCallback;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ComparisonChain;
-
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
@@ -64,7 +63,9 @@
private static final String TAG = PhoneFavoritesTileAdapter.class.getSimpleName();
private static final boolean DEBUG = false;
- public static final int ROW_LIMIT_DEFAULT = 1;
+ public static final int NO_ROW_LIMIT = -1;
+
+ public static final int ROW_LIMIT_DEFAULT = NO_ROW_LIMIT;
private ContactTileView.Listener mListener;
private OnDataSetChangedForAnimationListener mDataSetChangedListener;
@@ -155,7 +156,7 @@
mContactEntries = new ArrayList<ContactEntry>();
// Converting padding in dips to padding in pixels
mPaddingInPixels = mContext.getResources()
- .getDimensionPixelSize(R.dimen.contact_tile_divider_padding);
+ .getDimensionPixelSize(R.dimen.contact_tile_divider_width);
bindColumnIndices();
}
@@ -386,18 +387,24 @@
protected int getRowCount(int entryCount) {
if (entryCount == 0) return 0;
final int nonLimitedRows = ((entryCount - 1) / mColumnCount) + 1;
+ if (mMaxTiledRows == NO_ROW_LIMIT) {
+ return nonLimitedRows;
+ }
return Math.min(mMaxTiledRows, nonLimitedRows);
}
private int getMaxContactsInTiles() {
+ if (mMaxTiledRows == NO_ROW_LIMIT) {
+ return Integer.MAX_VALUE;
+ }
return mColumnCount * mMaxTiledRows;
}
public int getRowIndex(int entryIndex) {
- if (entryIndex < mMaxTiledRows * mColumnCount) {
+ if (entryIndex < getMaxContactsInTiles()) {
return entryIndex / mColumnCount;
} else {
- return entryIndex - mMaxTiledRows * mColumnCount + mMaxTiledRows;
+ return entryIndex - mMaxTiledRows * (mColumnCount + 1);
}
}
@@ -467,9 +474,13 @@
}
/**
- * Calculates the stable itemId for a particular entry based on its contactID
+ * Calculates the stable itemId for a particular entry based on the entry's contact ID. This
+ * stable itemId is used for animation purposes.
*/
public long getAdjustedItemId(long id) {
+ if (mMaxTiledRows == NO_ROW_LIMIT) {
+ return id;
+ }
return mMaxTiledRows + id;
}
@@ -479,7 +490,6 @@
}
@Override
-
public boolean areAllItemsEnabled() {
// No dividers, so all items are enabled.
return true;
@@ -541,7 +551,7 @@
@Override
public int getItemViewType(int position) {
- if (position < getRowCount(getMaxContactsInTiles())) {
+ if (position < getMaxContactsInTiles()) {
return ViewTypes.TOP;
} else {
return ViewTypes.FREQUENT;
@@ -700,6 +710,7 @@
private final int mRowPaddingEnd;
private final int mRowPaddingTop;
private final int mRowPaddingBottom;
+ private final float mHeightToWidthRatio;
private int mPosition;
private SwipeHelper mSwipeHelper;
private OnItemGestureListener mOnItemSwipeListener;
@@ -712,6 +723,9 @@
final Resources resources = mContext.getResources();
+ mHeightToWidthRatio = getResources().getFraction(
+ R.dimen.contact_tile_height_to_width_ratio, 1, 1);
+
if (mItemViewType == ViewTypes.TOP) {
// For tiled views, we still want padding to be set on the ContactTileRow.
// Otherwise the padding would be set around each of the tiles, which we don't want
@@ -723,8 +737,6 @@
R.dimen.favorites_row_start_padding);
mRowPaddingEnd = resources.getDimensionPixelSize(
R.dimen.favorites_row_end_padding);
-
- setBackgroundResource(R.drawable.bottom_border_background);
} else {
// For row views, padding is set on the view itself.
mRowPaddingTop = 0;
@@ -894,21 +906,22 @@
// Preferred width / height for images (excluding the padding).
// The actual width may be 1 pixel larger than this if we have a remainder.
- final int imageSize = (width - totalPaddingsInPixels) / mColumnCount;
- final int remainder = width - (imageSize * mColumnCount) - totalPaddingsInPixels;
+ final int imageWidth = (width - totalPaddingsInPixels) / mColumnCount;
+ final int remainder = width - (imageWidth * mColumnCount) - totalPaddingsInPixels;
+
+ final int height = (int) (mHeightToWidthRatio * imageWidth);
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
- final int childWidth = imageSize + child.getPaddingRight()
+ final int childWidth = imageWidth + child.getPaddingRight()
// Compensate for the remainder
+ (i < remainder ? 1 : 0);
- final int childHeight = imageSize;
child.measure(
MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY)
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
}
- setMeasuredDimension(width, imageSize + getPaddingTop() + getPaddingBottom());
+ setMeasuredDimension(width, height + getPaddingTop() + getPaddingBottom());
}
/**
@@ -919,7 +932,7 @@
* @return Index of the selected item in the cached array.
*/
public int getItemIndex(float itemX, float itemY) {
- if (mPosition < mMaxTiledRows) {
+ if (mMaxTiledRows == NO_ROW_LIMIT || mPosition < mMaxTiledRows) {
if (DEBUG) {
Log.v(TAG, String.valueOf(itemX) + " " + String.valueOf(itemY));
}
diff --git a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
index 611b3f1..7a2076d 100644
--- a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
+++ b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
@@ -1,15 +1,26 @@
package com.android.dialer.list;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.ContactsContract.PinnedPositions;
import android.test.AndroidTestCase;
+import com.android.contacts.common.ContactTileLoaderFactory;
+import com.android.contacts.common.list.ContactEntry;
+import com.android.dialer.list.PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener;
+
+import java.util.ArrayList;
+
public class PhoneFavoritesTileAdapterTest extends AndroidTestCase {
private PhoneFavoritesTileAdapter mAdapter;
+ private static final OnDataSetChangedForAnimationListener
+ sOnDataSetChangedForAnimationListener = new OnDataSetChangedForAnimationListener() {
+ @Override
+ public void onDataSetChangedForAnimation(long... idsInPlace) {}
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mAdapter = new PhoneFavoritesTileAdapter(getContext(), null, null, 3, 1);
- }
+ @Override
+ public void cacheOffsetsForDatasetChange() {}
+ };
/**
* TODO: Add tests
@@ -42,5 +53,124 @@
}
+ public void testGetRowIndex_NoRowLimit() {
+ mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+ assertEquals(0, mAdapter.getRowCount(0));
+ assertEquals(1, mAdapter.getRowCount(1));
+ assertEquals(1, mAdapter.getRowCount(2));
+ assertEquals(2, mAdapter.getRowCount(4));
+ assertEquals(4, mAdapter.getRowCount(7));
+ assertEquals(100, mAdapter.getRowCount(199));
+ mAdapter = getAdapterForTest(5, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+ assertEquals(0, mAdapter.getRowCount(0));
+ assertEquals(1, mAdapter.getRowCount(1));
+ assertEquals(1, mAdapter.getRowCount(3));
+ assertEquals(1, mAdapter.getRowCount(5));
+ assertEquals(2, mAdapter.getRowCount(7));
+ assertEquals(2, mAdapter.getRowCount(10));
+ assertEquals(40, mAdapter.getRowCount(199));
+ }
+
+ public void testGetItemId_NoRowLimit() {
+ mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+ assertEquals(0, mAdapter.getItemId(0));
+ assertEquals(1, mAdapter.getItemId(1));
+ assertEquals(5, mAdapter.getItemId(5));
+ assertEquals(10, mAdapter.getItemId(10));
+ }
+
+ public void testGetAdjustedItemId_NoRowLimit() {
+ mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+ assertEquals(0, mAdapter.getAdjustedItemId(0));
+ assertEquals(1, mAdapter.getAdjustedItemId(1));
+ assertEquals(5, mAdapter.getAdjustedItemId(5));
+ assertEquals(10, mAdapter.getAdjustedItemId(10));
+ }
+
+ public void testGetItem_NoRowLimit() {
+ mAdapter = getAdapterForTest(2, PhoneFavoritesTileAdapter.NO_ROW_LIMIT);
+ mAdapter.setContactCursor(getCursorForTest(5, 5));
+
+ final ArrayList<ContactEntry> row1 = new ArrayList<ContactEntry> ();
+ row1.add(getTestContactEntry(0, true));
+ row1.add(getTestContactEntry(1, true));
+ assertContactEntryRowsEqual(row1, mAdapter.getItem(0));
+
+ final ArrayList<ContactEntry> row3 = new ArrayList<ContactEntry> ();
+ row3.add(getTestContactEntry(4, true));
+ row3.add(getTestContactEntry(5, false));
+ assertContactEntryRowsEqual(row3, mAdapter.getItem(2));
+
+ final ArrayList<ContactEntry> row5 = new ArrayList<ContactEntry> ();
+ row5.add(getTestContactEntry(8, false));
+ row5.add(getTestContactEntry(9, false));
+ assertContactEntryRowsEqual(row5, mAdapter.getItem(4));
+ }
+
+ /**
+ * Ensures that PhoneFavoritesTileAdapter returns true for hasStableIds. This is needed for
+ * animation purposes.
+ */
+ public void testHasStableIds() {
+ mAdapter = new PhoneFavoritesTileAdapter(getContext(), null, null, 2, 2);
+ assertTrue(mAdapter.hasStableIds());
+ }
+
+ private PhoneFavoritesTileAdapter getAdapterForTest(int numCols, int numRows) {
+ return new PhoneFavoritesTileAdapter(getContext(), null,
+ sOnDataSetChangedForAnimationListener, numCols, numRows);
+ }
+
+ /**
+ * Returns a cursor containing starred and frequent contacts for test purposes.
+ *
+ * @param numStarred Number of starred contacts in the cursor. Cannot be a negative number.
+ * @param numFrequents Number of frequent contacts in the cursor. Cannot be a negative number.
+ * @return Cursor containing the required number of rows, each representing one ContactEntry
+ */
+ private Cursor getCursorForTest(int numStarred, int numFrequents) {
+ assertTrue(numStarred >= 0);
+ assertTrue(numFrequents >= 0);
+ final MatrixCursor c = new MatrixCursor(ContactTileLoaderFactory.COLUMNS_PHONE_ONLY);
+ int countId = 0;
+
+ // Add starred contact entries. These entries have the starred field set to 1 (true).
+ // The only field that really matters for testing is the contact id.
+ for (int i = 0; i < numStarred; i++) {
+ c.addRow(new Object[] {countId, null, 1, null, null, 0, 0, null, 0,
+ PinnedPositions.UNPINNED, countId});
+ countId++;
+ }
+
+ // Add frequent contact entries. These entries have the starred field set to 0 (false).
+ for (int i = 0; i < numFrequents; i++) {
+ c.addRow(new Object[] {countId, null, 0, null, null, 0, 0, null, 0,
+ PinnedPositions.UNPINNED, countId});
+ countId++;
+ }
+ return c;
+ }
+
+ /**
+ * Returns a ContactEntry with test data corresponding to the provided contact Id
+ *
+ * @param id Non-negative id
+ * @return ContactEntry item used for testing
+ */
+ private ContactEntry getTestContactEntry(int id, boolean isFavorite) {
+ ContactEntry contactEntry = new ContactEntry();
+ contactEntry.id = id;
+ contactEntry.isFavorite = isFavorite;
+ return contactEntry;
+ }
+
+ private void assertContactEntryRowsEqual(ArrayList<ContactEntry> expected,
+ ArrayList<ContactEntry> actual) {
+ assertEquals(expected.size(), actual.size());
+ for (int i = 0; i < actual.size(); i++) {
+ assertEquals(expected.get(i).id, actual.get(i).id);
+ assertEquals(expected.get(i).isFavorite, actual.get(i).isFavorite);
+ }
+ }
}