diff options
24 files changed, 236 insertions, 73 deletions
diff --git a/res/drawable-hdpi/ic_contact_info.png b/res/drawable-hdpi/ic_contact_info.png Binary files differdeleted file mode 100644 index 9c23000d9..000000000 --- a/res/drawable-hdpi/ic_contact_info.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_star_marked_as_fav.png b/res/drawable-hdpi/ic_star_marked_as_fav.png Binary files differdeleted file mode 100644 index 8a138c478..000000000 --- a/res/drawable-hdpi/ic_star_marked_as_fav.png +++ /dev/null diff --git a/res/drawable-hdpi/overflow_thumbnail.png b/res/drawable-hdpi/overflow_thumbnail.png Binary files differnew file mode 100644 index 000000000..57db353f7 --- /dev/null +++ b/res/drawable-hdpi/overflow_thumbnail.png diff --git a/res/drawable-hdpi/star_thumbnail.png b/res/drawable-hdpi/star_thumbnail.png Binary files differnew file mode 100644 index 000000000..1d4d5e184 --- /dev/null +++ b/res/drawable-hdpi/star_thumbnail.png diff --git a/res/drawable-mdpi/ic_contact_info.png b/res/drawable-mdpi/ic_contact_info.png Binary files differdeleted file mode 100644 index 5d35ec579..000000000 --- a/res/drawable-mdpi/ic_contact_info.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_star_marked_as_fav.png b/res/drawable-mdpi/ic_star_marked_as_fav.png Binary files differdeleted file mode 100644 index ee1b5ec1c..000000000 --- a/res/drawable-mdpi/ic_star_marked_as_fav.png +++ /dev/null diff --git a/res/drawable-mdpi/overflow_thumbnail.png b/res/drawable-mdpi/overflow_thumbnail.png Binary files differnew file mode 100644 index 000000000..c69937428 --- /dev/null +++ b/res/drawable-mdpi/overflow_thumbnail.png diff --git a/res/drawable-mdpi/star_thumbnail.png b/res/drawable-mdpi/star_thumbnail.png Binary files differnew file mode 100644 index 000000000..7b96272cf --- /dev/null +++ b/res/drawable-mdpi/star_thumbnail.png diff --git a/res/drawable-xhdpi/ic_contact_info.png b/res/drawable-xhdpi/ic_contact_info.png Binary files differdeleted file mode 100644 index 88d367b65..000000000 --- a/res/drawable-xhdpi/ic_contact_info.png +++ /dev/null diff --git a/res/drawable-xhdpi/ic_star_marked_as_fav.png b/res/drawable-xhdpi/ic_star_marked_as_fav.png Binary files differdeleted file mode 100644 index 372747a80..000000000 --- a/res/drawable-xhdpi/ic_star_marked_as_fav.png +++ /dev/null diff --git a/res/drawable-xhdpi/overflow_thumbnail.png b/res/drawable-xhdpi/overflow_thumbnail.png Binary files differnew file mode 100644 index 000000000..e538b9894 --- /dev/null +++ b/res/drawable-xhdpi/overflow_thumbnail.png diff --git a/res/drawable-xhdpi/star_thumbnail.png b/res/drawable-xhdpi/star_thumbnail.png Binary files differnew file mode 100644 index 000000000..a71262fb5 --- /dev/null +++ b/res/drawable-xhdpi/star_thumbnail.png diff --git a/res/drawable-xxhdpi/ic_contact_info.png b/res/drawable-xxhdpi/ic_contact_info.png Binary files differdeleted file mode 100644 index e5d2939cd..000000000 --- a/res/drawable-xxhdpi/ic_contact_info.png +++ /dev/null diff --git a/res/drawable-xxhdpi/ic_star_marked_as_fav.png b/res/drawable-xxhdpi/ic_star_marked_as_fav.png Binary files differdeleted file mode 100644 index 3eeff4c05..000000000 --- a/res/drawable-xxhdpi/ic_star_marked_as_fav.png +++ /dev/null diff --git a/res/drawable-xxhdpi/overflow_thumbnail.png b/res/drawable-xxhdpi/overflow_thumbnail.png Binary files differnew file mode 100644 index 000000000..7f3f73386 --- /dev/null +++ b/res/drawable-xxhdpi/overflow_thumbnail.png diff --git a/res/drawable-xxhdpi/star_thumbnail.png b/res/drawable-xxhdpi/star_thumbnail.png Binary files differnew file mode 100644 index 000000000..5f13fec1d --- /dev/null +++ b/res/drawable-xxhdpi/star_thumbnail.png diff --git a/res/layout/phone_favorite_regular_row_view.xml b/res/layout/phone_favorite_regular_row_view.xml index 012c9be2f..0d131f6fe 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 8806d3985..c4ad7800d 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 a8ddf2be7..b2d4bc560 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 17439521b..53d9c47e5 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -63,10 +63,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 81d9bfdc8..efc659fb6 100644 --- a/src/com/android/dialer/list/PhoneFavoriteFragment.java +++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java @@ -17,9 +17,7 @@ package com.android.dialer.list; 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.provider.CallLog; 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.ContactListItemView; 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen // 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen } /** - * 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen * 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen } 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 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen 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 85e721619..e855c88c5 100644 --- a/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java +++ b/src/com/android/dialer/list/PhoneFavoriteSquareTileView.java @@ -36,10 +36,6 @@ public class PhoneFavoriteSquareTileView extends PhoneFavoriteTileView { 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 @@ public class PhoneFavoriteSquareTileView extends PhoneFavoriteTileView { } @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 a85fc6a60..dff68b2be 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.contacts.common.list.ContactTileView; 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements } /** - * 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements } @Override - public boolean areAllItemsEnabled() { // No dividers, so all items are enabled. return true; @@ -541,7 +551,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements @Override public int getItemViewType(int position) { - if (position < getRowCount(getMaxContactsInTiles())) { + if (position < getMaxContactsInTiles()) { return ViewTypes.TOP; } else { return ViewTypes.FREQUENT; @@ -700,6 +710,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements // 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 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements * @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 611b3f1af..7a2076d8e 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 class PhoneFavoritesTileAdapterTest extends AndroidTestCase { } + 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); + } + } } |