PhoneFavoritesTileAdapter.java revision 55d3bb4a7f70d4a4359c31b3240f5740b788e643
1dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee/* 2dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Copyright (C) 2013 The Android Open Source Project 3dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 4dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); 5dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * you may not use this file except in compliance with the License. 6dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * You may obtain a copy of the License at 7dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 8dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * http://www.apache.org/licenses/LICENSE-2.0 9dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 10dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Unless required by applicable law or agreed to in writing, software 11dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * distributed under the License is distributed on an "AS IS" BASIS, 12dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * See the License for the specific language governing permissions and 14dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * limitations under the License. 15dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 16dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leepackage com.android.dialer.list; 17dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 18316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chenimport android.animation.ObjectAnimator; 19dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.ContentUris; 20dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.Context; 21dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.res.Resources; 22dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.database.Cursor; 23316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chenimport android.graphics.Color; 24316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chenimport android.graphics.Rect; 25dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.net.Uri; 26dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.Phone; 27dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.Contacts; 28dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.util.Log; 29dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.View; 30dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.ViewGroup; 31dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.BaseAdapter; 32dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.FrameLayout; 33dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 34dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactPhotoManager; 35dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactTileLoaderFactory; 36dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.R; 37dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactEntry; 38dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactTileView; 39dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 40dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport java.util.ArrayList; 41dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 42dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee/** 43dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Also allows for a configurable number of columns as well as a maximum row of tiled contacts. 44dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 45dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * This adapter has been rewritten to only support a maximum of one row for favorites. 46dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 47dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 48dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leepublic class PhoneFavoritesTileAdapter extends BaseAdapter { 49316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private static final String TAG = PhoneFavoritesTileAdapter.class.getSimpleName(); 50316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private static final boolean DEBUG = false; 51dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 526a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee public static final int ROW_LIMIT_DEFAULT = 1; 53dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 54316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Time period for an animation. */ 55316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private static final int ANIMATION_LENGTH = 300; 56316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 57316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private final ObjectAnimator mTranslateHorizontalAnimation; 58316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private final ObjectAnimator mTranslateVerticalAnimation; 59316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private final ObjectAnimator mAlphaAnimation; 60316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 61dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactTileView.Listener mListener; 62dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Context mContext; 63dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Resources mResources; 64316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 65316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Contact data stored in cache. This is used to populate the associated view. */ 66316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen protected ArrayList<ContactEntry> mContactEntries = null; 67316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Back up of the temporarily removed Contact during dragging. */ 68316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private ContactEntry mDraggedEntry = null; 69316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Position of the temporarily removed contact in the cache. */ 70316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mDraggedEntryIndex = -1; 71316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** New position of the temporarily removed contact in the cache. */ 72316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mDropEntryIndex = -1; 73316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Position of the contact pending removal. */ 74316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mPotentialRemoveEntryIndex = -1; 75316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 76dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactPhotoManager mPhotoManager; 77dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNumFrequents; 786a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int mNumStarred; 79dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 80dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mColumnCount; 816a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee private int mMaxTiledRows = ROW_LIMIT_DEFAULT; 82dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mStarredIndex; 83dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 84dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mIdIndex; 85dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mLookupIndex; 86dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPhotoUriIndex; 87dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNameIndex; 88dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPresenceIndex; 89dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mStatusIndex; 90dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 91dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 92dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Only valid when {@link DisplayType#STREQUENT_PHONE_ONLY} is true 93dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 94dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberIndex; 95dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberTypeIndex; 96dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberLabelIndex; 97dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 98dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private boolean mIsQuickContactEnabled = false; 99dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private final int mPaddingInPixels; 100dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 101316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Indicates whether a drag is in process. */ 102316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private boolean mInDragging = false; 103316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 10455d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee public PhoneFavoritesTileAdapter(Context context, ContactTileView.Listener listener, 105316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen int numCols) { 1066a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee this(context, listener, numCols, ROW_LIMIT_DEFAULT); 107dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 108dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 109316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public PhoneFavoritesTileAdapter(Context context, ContactTileView.Listener listener, 110316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen int numCols, int maxTiledRows) { 111dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mListener = listener; 112dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mContext = context; 113dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mResources = context.getResources(); 114dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mColumnCount = numCols; 115dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNumFrequents = 0; 116dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mMaxTiledRows = maxTiledRows; 117316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries = new ArrayList<ContactEntry>(); 118dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Converting padding in dips to padding in pixels 119dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPaddingInPixels = mContext.getResources() 120d6a16d364de95c8eb0d9c4f5a07d5ad6387c8470Yorke Lee .getDimensionPixelSize(R.dimen.contact_tile_divider_padding); 121316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 122316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // Initiates all animations. 123316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mAlphaAnimation = ObjectAnimator.ofFloat(null, "alpha", 1.f).setDuration(ANIMATION_LENGTH); 124316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 125316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation = ObjectAnimator.ofFloat(null, "translationX", 0.f). 126316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen setDuration(ANIMATION_LENGTH); 127316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 128316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation = ObjectAnimator.ofFloat(null, "translationY", 0.f).setDuration( 129316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen ANIMATION_LENGTH); 130316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 131dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee bindColumnIndices(); 132dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 133dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 134dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setPhotoLoader(ContactPhotoManager photoLoader) { 135dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoManager = photoLoader; 136dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 137dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 138dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setMaxRowCount(int maxRows) { 139dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mMaxTiledRows = maxRows; 140dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 141dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 142dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setColumnCount(int columnCount) { 143dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mColumnCount = columnCount; 144dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 145dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 146dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void enableQuickContact(boolean enableQuickContact) { 147dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mIsQuickContactEnabled = enableQuickContact; 148dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 149dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 150dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 151316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Indicates whether a drag is in process. 152316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 153316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param inDragging Boolean variable indicating whether there is a drag in process. 154316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 155316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void setInDragging(boolean inDragging) { 156316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mInDragging = inDragging; 157316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 158316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 159316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Gets whether the drag is in process. */ 160316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public boolean getInDragging() { 161316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return mInDragging; 162316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 163316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 164316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 165dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Sets the column indices for expected {@link Cursor} 166dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * based on {@link DisplayType}. 167dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 168dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void bindColumnIndices() { 169dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mIdIndex = ContactTileLoaderFactory.CONTACT_ID; 170dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; 171dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; 172dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNameIndex = ContactTileLoaderFactory.DISPLAY_NAME; 173dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStarredIndex = ContactTileLoaderFactory.STARRED; 174dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; 175dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; 176dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 177dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberIndex = ContactTileLoaderFactory.PHONE_NUMBER; 178dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberTypeIndex = ContactTileLoaderFactory.PHONE_NUMBER_TYPE; 179dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberLabelIndex = ContactTileLoaderFactory.PHONE_NUMBER_LABEL; 180dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 181dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 182dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 183dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Gets the number of frequents from the passed in cursor. 184dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 185dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * This methods is needed so the GroupMemberTileAdapter can override this. 186dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 187dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * @param cursor The cursor to get number of frequents from. 188dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 189dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void saveNumFrequentsFromCursor(Cursor cursor) { 1906a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee mNumFrequents = cursor.getCount() - mNumStarred; 191dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 192dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 193dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 194dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Creates {@link ContactTileView}s for each item in {@link Cursor}. 195dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 196dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Else use {@link ContactTileLoaderFactory} 197dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 198dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setContactCursor(Cursor cursor) { 199316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (cursor != null && !cursor.isClosed()) { 200316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mNumStarred = getNumStarredContacts(cursor); 201316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen saveNumFrequentsFromCursor(cursor); 202316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen saveCursorToCache(cursor); 203dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 204316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // cause a refresh of any views that rely on this data 205316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 206316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 207316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 208dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 209316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 210316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Saves the cursor data to the cache, to speed up UI changes. 211316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 212316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param cursor Returned cursor with data to populate the view. 213316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 214316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private void saveCursorToCache(Cursor cursor) { 215316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.clear(); 216316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen try { 217316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen cursor.moveToPosition(-1); 218316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen while (cursor.moveToNext()) { 219316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final long id = cursor.getLong(mIdIndex); 220316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final String photoUri = cursor.getString(mPhotoUriIndex); 221316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final String lookupKey = cursor.getString(mLookupIndex); 222316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 223316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final ContactEntry contact = new ContactEntry(); 224316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final String name = cursor.getString(mNameIndex); 225316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.name = (name != null) ? name : mResources.getString(R.string.missing_name); 226316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.status = cursor.getString(mStatusIndex); 227316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); 228316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.lookupKey = ContentUris.withAppendedId( 229316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), id); 230316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 231316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // Set phone number and label 232316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final int phoneNumberType = cursor.getInt(mPhoneNumberTypeIndex); 233316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final String phoneNumberCustomLabel = cursor.getString(mPhoneNumberLabelIndex); 234316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.phoneLabel = (String) Phone.getTypeLabel(mResources, phoneNumberType, 235316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen phoneNumberCustomLabel); 236316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contact.phoneNumber = cursor.getString(mPhoneNumberIndex); 237316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.add(contact); 238316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 239316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } finally { 240316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen cursor.close(); 241316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 242dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 243dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 244dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 245dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Iterates over the {@link Cursor} 246dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns position of the first NON Starred Contact 247dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns -1 if {@link DisplayType#STARRED_ONLY} 248dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns 0 if {@link DisplayType#FREQUENT_ONLY} 249dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 2506a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int getNumStarredContacts(Cursor cursor) { 251dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee cursor.moveToPosition(-1); 252dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee while (cursor.moveToNext()) { 253dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (cursor.getInt(mStarredIndex) == 0) { 254dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getPosition(); 255dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 256dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 257dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 258dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // There are not NON Starred contacts in cursor 259dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Set divider positon to end 260dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getCount(); 261dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 262dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 263316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 264316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Loads a contact from the cached list. 265316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 266316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param position Position of the Contact. 267316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @return Contact at the requested position. 268316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 269316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen protected ContactEntry getContactEntryFromCache(int position) { 270316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mContactEntries.size() <= position) return null; 271316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return mContactEntries.get(position); 272dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 273dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 274dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 275dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the number of frequents that will be displayed in the list. 276dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 277dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getNumFrequents() { 278dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return mNumFrequents; 279dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 280dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 281dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 282dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getCount() { 283316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mContactEntries == null) { 284dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return 0; 285dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 286dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 2876091473941d277ed3746143c1ca9bffdfbe2bd94Christine Chen int total = mNumFrequents + mNumStarred; 2886091473941d277ed3746143c1ca9bffdfbe2bd94Christine Chen 2896a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return total - (mMaxTiledRows * (mColumnCount - 1)); 290dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 291dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 2925fe874fbdfe0010b5f2439cf6c13eaee46d406eaYorke Lee public int getMaxTiledRows() { 2935fe874fbdfe0010b5f2439cf6c13eaee46d406eaYorke Lee return mMaxTiledRows; 2945fe874fbdfe0010b5f2439cf6c13eaee46d406eaYorke Lee } 2955fe874fbdfe0010b5f2439cf6c13eaee46d406eaYorke Lee 296dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 297dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the number of rows required to show the provided number of entries 298dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * with the current number of columns. 299dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 300dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int getRowCount(int entryCount) { 301dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (entryCount == 0) return 0; 302dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int nonLimitedRows = ((entryCount - 1) / mColumnCount) + 1; 3036a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return Math.min(mMaxTiledRows, nonLimitedRows); 3046a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee } 3056a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee 3066a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee private int getMaxContactsInTiles() { 3076a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return mColumnCount * mMaxTiledRows; 308dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 309dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 310316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen protected int getRowIndex(int entryIndex) { 311316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (entryIndex < mMaxTiledRows * mColumnCount) { 312316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return entryIndex / mColumnCount; 313316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 314316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return entryIndex - mMaxTiledRows * mColumnCount + mMaxTiledRows; 315316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 316316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 317316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 318dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getColumnCount() { 319dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return mColumnCount; 320dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 321dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 322dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 323dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns an ArrayList of the {@link ContactEntry}s that are to appear 324dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * on the row for the given position. 325dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 326dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 327dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public ArrayList<ContactEntry> getItem(int position) { 328dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ArrayList<ContactEntry> resultList = new ArrayList<ContactEntry>(mColumnCount); 329dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int contactIndex = position * mColumnCount; 3306a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee final int maxContactsInTiles = getMaxContactsInTiles(); 3316a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee if (position < getRowCount(maxContactsInTiles)) { 3326a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // Contacts that appear as tiles 333dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int columnCounter = 0; columnCounter < mColumnCount && 3346a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee contactIndex != maxContactsInTiles; columnCounter++) { 335316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen resultList.add(getContactEntryFromCache(contactIndex)); 336dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactIndex++; 337dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 338dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 3396a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // Contacts that appear as rows 3406a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // The actual position of the contact in the cursor is simply total the number of 3416a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // tiled contacts + the given position 3426a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee contactIndex = maxContactsInTiles + position - 1; 343316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen resultList.add(getContactEntryFromCache(contactIndex)); 344dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 3456a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee 346dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return resultList; 347dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 348dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 349dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 350dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public long getItemId(int position) { 351dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // As we show several selectable items for each ListView row, 352dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // we can not determine a stable id. But as we don't rely on ListView's selection, 353dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // this should not be a problem. 354dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return position; 355dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 356dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 357dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 358dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean areAllItemsEnabled() { 359dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // No dividers, so all items are enabled. 360dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return true; 361dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 362dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 363dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 364dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean isEnabled(int position) { 3656a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return true; 366dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 367dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 368dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 369316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void notifyDataSetChanged() { 370316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (DEBUG) { 371316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen Log.v(TAG, "nofigyDataSetChanged"); 372316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 373316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen super.notifyDataSetChanged(); 374316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 375316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 376316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 377316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Configures the animation for each view. 378316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 379316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param contactTileRowView The row to be animated. 380316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param position The position of the row. 381316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param itemViewType The type of the row. 382316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 383316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private void configureAnimationToView(ContactTileRow contactTileRowView, int position, 384316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen int itemViewType) { 385316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mInDragging) { 386316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // If the one item above the row is being dragged, animates all following items to 387316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // move up. If the item is a favorite tile, animate it to appear from right. 388316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (position >= getRowIndex(mDraggedEntryIndex)) { 389316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (itemViewType == ViewTypes.FREQUENT) { 390316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setTarget(contactTileRowView); 391316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setFloatValues(contactTileRowView.getHeight(), 0); 392316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.clone().start(); 393316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 394316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView.animateTilesAppearLeft(mDraggedEntryIndex - 395316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen position * mColumnCount); 396316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 397316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 398316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else if (mDropEntryIndex != -1) { 399316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // If one item is dropped in front the row, animate all following rows to shift down. 400316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // If the item is a favorite tile, animate it to appear from left. 401316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (position >= getRowIndex(mDropEntryIndex)) { 402316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (itemViewType == ViewTypes.FREQUENT) { 403316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (position == getRowIndex(mDropEntryIndex) || position == mMaxTiledRows) { 404316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView.setVisibility(View.VISIBLE); 405316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mAlphaAnimation.setTarget(contactTileRowView); 406316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mAlphaAnimation.clone().start(); 407316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 408316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setTarget(contactTileRowView); 409316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setFloatValues(-contactTileRowView.getHeight(), 410316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 0); 411316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.clone().start(); 412316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 413316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 414316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView.animateTilesAppearRight(mDropEntryIndex + 1 - 415316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen position * mColumnCount); 416316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 417316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 418316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else if (mPotentialRemoveEntryIndex != -1) { 419316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // If one item is to be removed above this row, animate the row to shift up. If it is 420316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // a favorite contact tile, animate it to appear from right. 421316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (position >= getRowIndex(mPotentialRemoveEntryIndex)) { 422316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (itemViewType == ViewTypes.FREQUENT) { 423316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setTarget(contactTileRowView); 424316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.setFloatValues(contactTileRowView.getHeight(), 0); 425316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateVerticalAnimation.clone().start(); 426316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 427316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView.animateTilesAppearLeft( 428316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPotentialRemoveEntryIndex - position * mColumnCount); 429316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 430316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 431316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 432316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 433316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 434316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen @Override 435dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public View getView(int position, View convertView, ViewGroup parent) { 43655d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee if (DEBUG) { 43755d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee Log.v(TAG, "get view for " + String.valueOf(position)); 43855d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee } 439dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int itemViewType = getItemViewType(position); 440dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 4416091473941d277ed3746143c1ca9bffdfbe2bd94Christine Chen ContactTileRow contactTileRowView = (ContactTileRow) convertView; 4426091473941d277ed3746143c1ca9bffdfbe2bd94Christine Chen 443dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ArrayList<ContactEntry> contactList = getItem(position); 444dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 445dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (contactTileRowView == null) { 446dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Creating new row if needed 447316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView = new ContactTileRow(mContext, itemViewType, position); 448dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 449dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 450316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTileRowView.configureRow(contactList, position, position == getCount() - 1); 451316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 452316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen configureAnimationToView(contactTileRowView, position, itemViewType); 453316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 454dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return contactTileRowView; 455dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 456dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 457dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int getLayoutResourceId(int viewType) { 458dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (viewType) { 459dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee case ViewTypes.FREQUENT: 460dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return R.layout.phone_favorite_regular_row_view; 461d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 462dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return R.layout.phone_favorite_tile_view; 463dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 464dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee throw new IllegalArgumentException("Unrecognized viewType " + viewType); 465dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 466dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 467dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 468dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getViewTypeCount() { 469dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return ViewTypes.COUNT; 470dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 471dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 472dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 473dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getItemViewType(int position) { 4746a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee if (position < getRowCount(getMaxContactsInTiles())) { 475d99993213962df64c9d76005df86c2fb83fca074Yorke Lee return ViewTypes.TOP; 476dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 477dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return ViewTypes.FREQUENT; 478dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 479dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 480dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 481dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 482dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the "frequent header" position. Only available when STREQUENT or 483dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * STREQUENT_PHONE_ONLY is used for its display type. 4846a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * 4856a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * TODO krelease: We shouldn't need this method once we get rid of the frequent header 4866a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * in the merged adapter 487dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 488dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getFrequentHeaderPosition() { 4896a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return getRowCount(mNumStarred); 490dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 491dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 492dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 493316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Temporarily removes a contact from the list for UI refresh. Stores data for this contact 494316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * in the back-up variable. 495316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 496316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param index Position of the contact to be removed. 497316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 498316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void popContactEntry(int index) { 499316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (index >= 0 && index < mContactEntries.size()) { 500316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = mContactEntries.get(index); 501316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntryIndex = index; 502316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.remove(index); 503316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 504316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 505316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 506316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 507316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 508316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Drops the temporarily removed contact to the desired location in the list. 509316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 510316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param index Location where the contact will be dropped. 511316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 512316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void dropContactEntry(int index) { 513316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mDraggedEntry != null) { 514316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (index >= 0 && index <= mContactEntries.size()) { 515316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.add(index, mDraggedEntry); 516316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDropEntryIndex = index; 517316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else if (mDraggedEntryIndex >= 0 && mDraggedEntryIndex <= mContactEntries.size()) { 518316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** If the index is invalid, falls back to the original position of the contact. */ 519316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.add(mDraggedEntryIndex, mDraggedEntry); 520316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDropEntryIndex = mDraggedEntryIndex; 521316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 522316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = null; 523316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 524316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 525316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 526316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 527316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 528316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Sets an item to for pending removal. If the user does not click the undo button, the item 529316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * will be removed at the next interaction. 530316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 531316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param index Index of the item to be removed. 532316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 533316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void setPotentialRemoveEntryIndex(int index) { 534316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPotentialRemoveEntryIndex = index; 535316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 536316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 537316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 538316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Removes a contact entry from the cache. 539316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 540316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @return True is an item is removed. False is there is no item to be removed. 541316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 542316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public boolean removeContactEntry() { 543316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mPotentialRemoveEntryIndex >= 0 && mPotentialRemoveEntryIndex < mContactEntries.size()) { 544316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.remove(mPotentialRemoveEntryIndex); 545316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 546316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return true; 547316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 548316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return false; 549316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 550316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 551316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 552316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Resets the item for pending removal. 553316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 554316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void undoPotentialRemoveEntryIndex() { 555316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPotentialRemoveEntryIndex = -1; 556316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 557316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 558316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 559316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Clears all temporary variables at a new interaction. 560316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 561316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void cleanTempVariables() { 562316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntryIndex = -1; 563316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDropEntryIndex = -1; 564316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = null; 565316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPotentialRemoveEntryIndex = -1; 566316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 567316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 568316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 569dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Acts as a row item composed of {@link ContactTileView} 570dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 571dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * TODO: FREQUENT doesn't really need it. Just let {@link #getView} return 572dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 573316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public class ContactTileRow extends FrameLayout { 574dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mItemViewType; 575dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mLayoutResId; 576d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingStart; 577d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingEnd; 578d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingTop; 579d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingBottom; 580316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mPosition; 581dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 582316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public ContactTileRow(Context context, int itemViewType, int position) { 583dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super(context); 584dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mItemViewType = itemViewType; 585dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mLayoutResId = getLayoutResourceId(mItemViewType); 586316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPosition = position; 587dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 588d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final Resources resources = mContext.getResources(); 589d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingStart = resources.getDimensionPixelSize( 590d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_start_padding); 591d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingEnd = resources.getDimensionPixelSize( 592d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_end_padding); 593d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingTop = resources.getDimensionPixelSize( 594d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_top_padding); 595d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingBottom = resources.getDimensionPixelSize( 596d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_bottom_padding); 597d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 598d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setBackgroundResource(R.drawable.bottom_border_background); 599d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 600d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setPaddingRelative(mRowPaddingStart, mRowPaddingTop, mRowPaddingEnd, 601d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingBottom); 602d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 603dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Remove row (but not children) from accessibility node tree. 604dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); 605dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 606dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 607dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 608dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Configures the row to add {@link ContactEntry}s information to the views 609dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 610316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void configureRow(ArrayList<ContactEntry> list, int position, boolean isLastRow) { 611dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int columnCount = mItemViewType == ViewTypes.FREQUENT ? 1 : mColumnCount; 612316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mPosition = position; 613dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 614dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Adding tiles to row and filling in contact information 615dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int columnCounter = 0; columnCounter < columnCount; columnCounter++) { 616dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ContactEntry entry = 617dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee columnCounter < list.size() ? list.get(columnCounter) : null; 618dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee addTileFromEntry(entry, columnCounter, isLastRow); 619dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 620dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 621dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 622dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void addTileFromEntry(ContactEntry entry, int childIndex, boolean isLastRow) { 623316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final PhoneFavoriteTileView contactTile; 624dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 625dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (getChildCount() <= childIndex) { 626dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 627316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTile = (PhoneFavoriteTileView) inflate(mContext, mLayoutResId, null); 628dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Note: the layoutparam set here is only actually used for FREQUENT. 629dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // We override onMeasure() for STARRED and we don't care the layout param there. 630d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final Resources resources = mContext.getResources(); 631dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( 632dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ViewGroup.LayoutParams.WRAP_CONTENT, 633dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ViewGroup.LayoutParams.WRAP_CONTENT); 634dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 635dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee params.setMargins( 636316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen resources.getDimensionPixelSize(R.dimen.detail_item_side_margin), 0, 637316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen resources.getDimensionPixelSize(R.dimen.detail_item_side_margin), 0); 638dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setLayoutParams(params); 639dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setPhotoManager(mPhotoManager); 640dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setListener(mListener); 641dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee addView(contactTile); 642dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 643316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTile = (PhoneFavoriteTileView) getChildAt(childIndex); 644dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 645dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.loadFromContact(entry); 646316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTile.setId(childIndex); 647dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 648d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 649dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Setting divider visibilities 650dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setPaddingRelative(0, 0, 651d99993213962df64c9d76005df86c2fb83fca074Yorke Lee childIndex >= mColumnCount - 1 ? 0 : mPaddingInPixels, 0); 652dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 653dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee case ViewTypes.FREQUENT: 654dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setHorizontalDividerVisibility( 655dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee isLastRow ? View.GONE : View.VISIBLE); 656dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 657dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 658dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 659dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 660316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen contactTile.setupFavoriteContactCard(); 661dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 662dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 663dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 664dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 665dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 666d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 667dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee onLayoutForTiles(); 668dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 669dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 670dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super.onLayout(changed, left, top, right, bottom); 671dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 672dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 673dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 674dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 675dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void onLayoutForTiles() { 676dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int count = getChildCount(); 677dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 678dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Just line up children horizontally. 679d99993213962df64c9d76005df86c2fb83fca074Yorke Lee int childLeft = getPaddingStart(); 680dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int i = 0; i < count; i++) { 681dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final View child = getChildAt(i); 682dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 683dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Note MeasuredWidth includes the padding. 684dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childWidth = child.getMeasuredWidth(); 685dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); 686dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee childLeft += childWidth; 687dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 688dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 689dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 690dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 691dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 692dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 693d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 694dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee onMeasureForTiles(widthMeasureSpec); 695dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 696dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 697dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super.onMeasure(widthMeasureSpec, heightMeasureSpec); 698dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 699dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 700dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 701dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 702dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void onMeasureForTiles(int widthMeasureSpec) { 703dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int width = MeasureSpec.getSize(widthMeasureSpec); 704dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 705dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childCount = getChildCount(); 706dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (childCount == 0) { 707dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Just in case... 708dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee setMeasuredDimension(width, 0); 709dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 710dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 711dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 712dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 1. Calculate image size. 713dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // = ([total width] - [total padding]) / [child count] 714dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 715dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 2. Set it to width/height of each children. 716dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // If we have a remainder, some tiles will have 1 pixel larger width than its height. 717dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 718dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 3. Set the dimensions of itself. 719dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Let width = given width. 720dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Let height = image size + bottom paddding. 721dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 722d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final int totalPaddingsInPixels = (mColumnCount - 1) * mPaddingInPixels 723d99993213962df64c9d76005df86c2fb83fca074Yorke Lee + mRowPaddingStart + mRowPaddingEnd; 724dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 725dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Preferred width / height for images (excluding the padding). 726dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // The actual width may be 1 pixel larger than this if we have a remainder. 727dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int imageSize = (width - totalPaddingsInPixels) / mColumnCount; 728dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int remainder = width - (imageSize * mColumnCount) - totalPaddingsInPixels; 729dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 730dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int i = 0; i < childCount; i++) { 731dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final View child = getChildAt(i); 732dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childWidth = imageSize + child.getPaddingRight() 733dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Compensate for the remainder 734dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee + (i < remainder ? 1 : 0); 735d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final int childHeight = imageSize; 736dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee child.measure( 737dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), 738dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY) 739dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ); 740dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 741d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setMeasuredDimension(width, imageSize + getPaddingTop() + getPaddingBottom()); 742dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 743316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 744316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 745316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Gets the index of the item at the specified coordinates. 746316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 747316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param itemX X-coordinate of the selected item. 748316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param itemY Y-coordinate of the selected item. 749316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @return Index of the selected item in the cached array. 750316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 751316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public int getItemIndex(float itemX, float itemY) { 752316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mPosition < mMaxTiledRows) { 753316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen final Rect childRect = new Rect(); 754316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (DEBUG) { 755316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen Log.v(TAG, String.valueOf(itemX) + " " + String.valueOf(itemY)); 756316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 757316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen for (int i = 0; i < getChildCount(); ++i) { 758316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** If the row contains multiple tiles, checks each tile to see if the point 759316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * is contained in the tile. */ 760316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen getChildAt(i).getHitRect(childRect); 761316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (DEBUG) { 762316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen Log.v(TAG, childRect.toString()); 763316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 764316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (childRect.contains((int)itemX, (int)itemY)) { 765316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** If the point is contained in the rectangle, computes the index of the 766316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * item in the cached array. */ 767316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return i + (mPosition) * mColumnCount; 768316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 769316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 770316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } else { 771316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** If the selected item is one of the rows, compute the index. */ 772316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return (mPosition - mMaxTiledRows) + mColumnCount * mMaxTiledRows; 773316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 774316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return -1; 775316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 776316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 777316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public PhoneFavoritesTileAdapter getTileAdapter() { 778316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return PhoneFavoritesTileAdapter.this; 779316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 780316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 781316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void animateTilesAppearLeft(int index) { 782316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen for (int i = index; i < getChildCount(); ++i) { 783316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen View childView = getChildAt(i); 784316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.setTarget(childView); 785316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.setFloatValues(childView.getWidth(), 0); 786316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.clone().start(); 787316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 788316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 789316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 790316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void animateTilesAppearRight(int index) { 791316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen for (int i = index; i < getChildCount(); ++i) { 792316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen View childView = getChildAt(i); 793316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.setTarget(childView); 794316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.setFloatValues(-childView.getWidth(), 0); 795316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mTranslateHorizontalAnimation.clone().start(); 796316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 797316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 798316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 799316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public int getPosition() { 800316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return mPosition; 801316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 802dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 803dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 804dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected static class ViewTypes { 805d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int COUNT = 2; 806d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int FREQUENT = 0; 807d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int TOP = 1; 808dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 809dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee} 810