PhoneFavoritesTileAdapter.java revision 6a8402939f667ab70bd0043ed0859f8afbc012ec
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 18dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.ContentUris; 19dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.Context; 20dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.res.Resources; 21dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.database.Cursor; 22dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.graphics.drawable.Drawable; 23dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.net.Uri; 24dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.Phone; 25dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.Contacts; 26dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.util.Log; 27dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.View; 28dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.ViewGroup; 29dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.BaseAdapter; 30dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.FrameLayout; 31dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 32dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactPhotoManager; 33dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactTileLoaderFactory; 34dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.R; 35dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactEntry; 36dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactTileAdapter; 37dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactTileView; 38dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 39dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport java.util.ArrayList; 40dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 41dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee/** 42dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Also allows for a configurable number of columns as well as a maximum row of tiled contacts. 43dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 44dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * This adapter has been rewritten to only support a maximum of one row for favorites. 45dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 46dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 47dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leepublic class PhoneFavoritesTileAdapter extends BaseAdapter { 48dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private static final String TAG = ContactTileAdapter.class.getSimpleName(); 49dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 506a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee public static final int ROW_LIMIT_DEFAULT = 1; 51dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 52dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactTileView.Listener mListener; 53dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Context mContext; 54dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Resources mResources; 55dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected Cursor mContactCursor = null; 56dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactPhotoManager mPhotoManager; 57dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNumFrequents; 586a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int mNumStarred; 59dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 60dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mColumnCount; 616a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee private int mMaxTiledRows = ROW_LIMIT_DEFAULT; 62dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mStarredIndex; 63dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 64dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mIdIndex; 65dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mLookupIndex; 66dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPhotoUriIndex; 67dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNameIndex; 68dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPresenceIndex; 69dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mStatusIndex; 70dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 71dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 72dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Only valid when {@link DisplayType#STREQUENT_PHONE_ONLY} is true 73dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 74dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberIndex; 75dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberTypeIndex; 76dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberLabelIndex; 77dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 78dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private boolean mIsQuickContactEnabled = false; 79dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private final int mPaddingInPixels; 80dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 81dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public PhoneFavoritesTileAdapter(Context context, ContactTileView.Listener listener, int numCols) { 826a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee this(context, listener, numCols, ROW_LIMIT_DEFAULT); 83dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 84dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 85dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public PhoneFavoritesTileAdapter(Context context, ContactTileView.Listener listener, int numCols, 86dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int maxTiledRows) { 87dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mListener = listener; 88dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mContext = context; 89dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mResources = context.getResources(); 90dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mColumnCount = numCols; 91dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNumFrequents = 0; 92dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mMaxTiledRows = maxTiledRows; 93dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 94dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Converting padding in dips to padding in pixels 95dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPaddingInPixels = mContext.getResources() 96d99993213962df64c9d76005df86c2fb83fca074Yorke Lee .getDimensionPixelSize(R.dimen.phone_contact_tile_divider_padding); 97dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee bindColumnIndices(); 98dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 99dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 100dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setPhotoLoader(ContactPhotoManager photoLoader) { 101dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoManager = photoLoader; 102dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 103dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 104dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setMaxRowCount(int maxRows) { 105dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mMaxTiledRows = maxRows; 106dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 107dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 108dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setColumnCount(int columnCount) { 109dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mColumnCount = columnCount; 110dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 111dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 112dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void enableQuickContact(boolean enableQuickContact) { 113dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mIsQuickContactEnabled = enableQuickContact; 114dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 115dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 116dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 117dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Sets the column indices for expected {@link Cursor} 118dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * based on {@link DisplayType}. 119dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 120dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void bindColumnIndices() { 121dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mIdIndex = ContactTileLoaderFactory.CONTACT_ID; 122dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; 123dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; 124dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNameIndex = ContactTileLoaderFactory.DISPLAY_NAME; 125dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStarredIndex = ContactTileLoaderFactory.STARRED; 126dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; 127dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; 128dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 129dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberIndex = ContactTileLoaderFactory.PHONE_NUMBER; 130dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberTypeIndex = ContactTileLoaderFactory.PHONE_NUMBER_TYPE; 131dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberLabelIndex = ContactTileLoaderFactory.PHONE_NUMBER_LABEL; 132dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 133dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 134dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 135dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Gets the number of frequents from the passed in cursor. 136dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 137dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * This methods is needed so the GroupMemberTileAdapter can override this. 138dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 139dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * @param cursor The cursor to get number of frequents from. 140dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 141dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void saveNumFrequentsFromCursor(Cursor cursor) { 1426a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee mNumFrequents = cursor.getCount() - mNumStarred; 143dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 144dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 145dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 146dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Creates {@link ContactTileView}s for each item in {@link Cursor}. 147dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 148dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Else use {@link ContactTileLoaderFactory} 149dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 150dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setContactCursor(Cursor cursor) { 151dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mContactCursor = cursor; 1526a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee mNumStarred = getNumStarredContacts(cursor); 153dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 154dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee saveNumFrequentsFromCursor(cursor); 155dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 156dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // cause a refresh of any views that rely on this data 157dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee notifyDataSetChanged(); 158dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 159dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 160dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 161dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Iterates over the {@link Cursor} 162dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns position of the first NON Starred Contact 163dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns -1 if {@link DisplayType#STARRED_ONLY} 164dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns 0 if {@link DisplayType#FREQUENT_ONLY} 165dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 1666a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int getNumStarredContacts(Cursor cursor) { 167dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (cursor == null || cursor.isClosed()) { 168dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee throw new IllegalStateException("Unable to access cursor"); 169dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 170dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 171dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee cursor.moveToPosition(-1); 172dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee while (cursor.moveToNext()) { 173dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (cursor.getInt(mStarredIndex) == 0) { 174dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getPosition(); 175dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 176dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 177dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 178dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // There are not NON Starred contacts in cursor 179dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Set divider positon to end 180dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getCount(); 181dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 182dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 183dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected ContactEntry createContactEntryFromCursor(Cursor cursor, int position) { 184dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // If the loader was canceled we will be given a null cursor. 185dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // In that case, show an empty list of contacts. 186dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (cursor == null || cursor.isClosed() || cursor.getCount() <= position) return null; 187dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 188dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee cursor.moveToPosition(position); 189dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee long id = cursor.getLong(mIdIndex); 190dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee String photoUri = cursor.getString(mPhotoUriIndex); 191dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee String lookupKey = cursor.getString(mLookupIndex); 192dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 193dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ContactEntry contact = new ContactEntry(); 194dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee String name = cursor.getString(mNameIndex); 195dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.name = (name != null) ? name : mResources.getString(R.string.missing_name); 196dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.status = cursor.getString(mStatusIndex); 197dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); 198dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.lookupKey = ContentUris.withAppendedId( 199dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), id); 200dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 201dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Set phone number and label 202dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int phoneNumberType = cursor.getInt(mPhoneNumberTypeIndex); 203dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee String phoneNumberCustomLabel = cursor.getString(mPhoneNumberLabelIndex); 204dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.phoneLabel = (String) Phone.getTypeLabel(mResources, phoneNumberType, 205dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee phoneNumberCustomLabel); 206dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contact.phoneNumber = cursor.getString(mPhoneNumberIndex); 207dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 208dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return contact; 209dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 210dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 211dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 212dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the number of frequents that will be displayed in the list. 213dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 214dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getNumFrequents() { 215dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return mNumFrequents; 216dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 217dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 218dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 219dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getCount() { 220dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (mContactCursor == null || mContactCursor.isClosed()) { 221dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return 0; 222dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 223dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 2246a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee final int total = mNumFrequents + mNumStarred; 2256a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return total - (mMaxTiledRows * (mColumnCount - 1)); 226dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 227dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 228dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 229dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the number of rows required to show the provided number of entries 230dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * with the current number of columns. 231dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 232dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int getRowCount(int entryCount) { 233dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (entryCount == 0) return 0; 234dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int nonLimitedRows = ((entryCount - 1) / mColumnCount) + 1; 2356a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return Math.min(mMaxTiledRows, nonLimitedRows); 2366a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee } 2376a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee 2386a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee private int getMaxContactsInTiles() { 2396a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return mColumnCount * mMaxTiledRows; 240dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 241dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 242dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getColumnCount() { 243dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return mColumnCount; 244dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 245dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 246dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 247dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns an ArrayList of the {@link ContactEntry}s that are to appear 248dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * on the row for the given position. 249dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 250dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 251dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public ArrayList<ContactEntry> getItem(int position) { 252dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ArrayList<ContactEntry> resultList = new ArrayList<ContactEntry>(mColumnCount); 253dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int contactIndex = position * mColumnCount; 2546a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee final int maxContactsInTiles = getMaxContactsInTiles(); 2556a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee if (position < getRowCount(maxContactsInTiles)) { 2566a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // Contacts that appear as tiles 257dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int columnCounter = 0; columnCounter < mColumnCount && 2586a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee contactIndex != maxContactsInTiles; columnCounter++) { 259dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex)); 260dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactIndex++; 261dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 262dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 2636a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // Contacts that appear as rows 2646a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // The actual position of the contact in the cursor is simply total the number of 2656a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee // tiled contacts + the given position 2666a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee contactIndex = maxContactsInTiles + position - 1; 267dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex)); 268dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 2696a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee 270dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return resultList; 271dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 272dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 273dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 274dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public long getItemId(int position) { 275dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // As we show several selectable items for each ListView row, 276dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // we can not determine a stable id. But as we don't rely on ListView's selection, 277dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // this should not be a problem. 278dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return position; 279dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 280dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 281dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 282dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean areAllItemsEnabled() { 283dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // No dividers, so all items are enabled. 284dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return true; 285dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 286dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 287dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 288dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean isEnabled(int position) { 2896a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return true; 290dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 291dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 292dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 293dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public View getView(int position, View convertView, ViewGroup parent) { 294dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int itemViewType = getItemViewType(position); 295dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 296dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ContactTileRow contactTileRowView = (ContactTileRow) convertView; 297dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ArrayList<ContactEntry> contactList = getItem(position); 298dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 299dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (contactTileRowView == null) { 300dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Creating new row if needed 301dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTileRowView = new ContactTileRow(mContext, itemViewType); 302dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 303dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 304dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTileRowView.configureRow(contactList, position == getCount() - 1); 305dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return contactTileRowView; 306dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 307dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 308dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int getLayoutResourceId(int viewType) { 309dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (viewType) { 310dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee case ViewTypes.FREQUENT: 311dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return R.layout.phone_favorite_regular_row_view; 312d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 313dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return R.layout.phone_favorite_tile_view; 314dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 315dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee throw new IllegalArgumentException("Unrecognized viewType " + viewType); 316dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 317dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 318dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 319dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getViewTypeCount() { 320dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return ViewTypes.COUNT; 321dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 322dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 323dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 324dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getItemViewType(int position) { 3256a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee if (position < getRowCount(getMaxContactsInTiles())) { 326d99993213962df64c9d76005df86c2fb83fca074Yorke Lee return ViewTypes.TOP; 327dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 328dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return ViewTypes.FREQUENT; 329dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 330dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 331dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 332dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 333dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the "frequent header" position. Only available when STREQUENT or 334dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * STREQUENT_PHONE_ONLY is used for its display type. 3356a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * 3366a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * TODO krelease: We shouldn't need this method once we get rid of the frequent header 3376a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee * in the merged adapter 338dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 339dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getFrequentHeaderPosition() { 3406a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee return getRowCount(mNumStarred); 341dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 342dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 343dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 344dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Acts as a row item composed of {@link ContactTileView} 345dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 346dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * TODO: FREQUENT doesn't really need it. Just let {@link #getView} return 347dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 348dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private class ContactTileRow extends FrameLayout { 349dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mItemViewType; 350dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mLayoutResId; 351d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingStart; 352d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingEnd; 353d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingTop; 354d99993213962df64c9d76005df86c2fb83fca074Yorke Lee private final int mRowPaddingBottom; 355dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 356dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public ContactTileRow(Context context, int itemViewType) { 357dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super(context); 358dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mItemViewType = itemViewType; 359dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mLayoutResId = getLayoutResourceId(mItemViewType); 360dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 361d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final Resources resources = mContext.getResources(); 362d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingStart = resources.getDimensionPixelSize( 363d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_start_padding); 364d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingEnd = resources.getDimensionPixelSize( 365d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_end_padding); 366d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingTop = resources.getDimensionPixelSize( 367d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_top_padding); 368d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingBottom = resources.getDimensionPixelSize( 369d99993213962df64c9d76005df86c2fb83fca074Yorke Lee R.dimen.favorites_row_bottom_padding); 370d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 371d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setBackgroundResource(R.drawable.bottom_border_background); 372d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 373d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setPaddingRelative(mRowPaddingStart, mRowPaddingTop, mRowPaddingEnd, 374d99993213962df64c9d76005df86c2fb83fca074Yorke Lee mRowPaddingBottom); 375d99993213962df64c9d76005df86c2fb83fca074Yorke Lee 376dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Remove row (but not children) from accessibility node tree. 377dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); 378dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 379dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 380dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 381dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Configures the row to add {@link ContactEntry}s information to the views 382dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 383dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void configureRow(ArrayList<ContactEntry> list, boolean isLastRow) { 384dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int columnCount = mItemViewType == ViewTypes.FREQUENT ? 1 : mColumnCount; 385dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 386dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Adding tiles to row and filling in contact information 387dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int columnCounter = 0; columnCounter < columnCount; columnCounter++) { 388dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ContactEntry entry = 389dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee columnCounter < list.size() ? list.get(columnCounter) : null; 390dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee addTileFromEntry(entry, columnCounter, isLastRow); 391dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 392dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 393dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 394dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void addTileFromEntry(ContactEntry entry, int childIndex, boolean isLastRow) { 395dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final ContactTileView contactTile; 396dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 397dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (getChildCount() <= childIndex) { 398dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 399dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile = (ContactTileView) inflate(mContext, mLayoutResId, null); 400dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Note: the layoutparam set here is only actually used for FREQUENT. 401dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // We override onMeasure() for STARRED and we don't care the layout param there. 402d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final Resources resources = mContext.getResources(); 403dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( 404dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ViewGroup.LayoutParams.WRAP_CONTENT, 405dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ViewGroup.LayoutParams.WRAP_CONTENT); 406dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 407dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee params.setMargins( 408dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee resources.getDimensionPixelSize(R.dimen.detail_item_side_margin), 409dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 0, 410dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee resources.getDimensionPixelSize(R.dimen.detail_item_side_margin), 411dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 0); 412dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setLayoutParams(params); 413dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setPhotoManager(mPhotoManager); 414dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setListener(mListener); 415dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee addView(contactTile); 416dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } else { 417dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile = (ContactTileView) getChildAt(childIndex); 418dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 419dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.loadFromContact(entry); 420dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 421d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 422dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Setting divider visibilities 423dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setPaddingRelative(0, 0, 424d99993213962df64c9d76005df86c2fb83fca074Yorke Lee childIndex >= mColumnCount - 1 ? 0 : mPaddingInPixels, 0); 425dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 426dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee case ViewTypes.FREQUENT: 427dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee contactTile.setHorizontalDividerVisibility( 428dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee isLastRow ? View.GONE : View.VISIBLE); 429dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 430dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 431dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee break; 432dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 433dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 434dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 435dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 436dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 437dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 438d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 439dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee onLayoutForTiles(); 440dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 441dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 442dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super.onLayout(changed, left, top, right, bottom); 443dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 444dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 445dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 446dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 447dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void onLayoutForTiles() { 448dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int count = getChildCount(); 449dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 450dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Just line up children horizontally. 451d99993213962df64c9d76005df86c2fb83fca074Yorke Lee int childLeft = getPaddingStart(); 452dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int i = 0; i < count; i++) { 453dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final View child = getChildAt(i); 454dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 455dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Note MeasuredWidth includes the padding. 456dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childWidth = child.getMeasuredWidth(); 457dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); 458dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee childLeft += childWidth; 459dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 460dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 461dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 462dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 463dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 464dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee switch (mItemViewType) { 465d99993213962df64c9d76005df86c2fb83fca074Yorke Lee case ViewTypes.TOP: 466dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee onMeasureForTiles(widthMeasureSpec); 467dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 468dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee default: 469dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee super.onMeasure(widthMeasureSpec, heightMeasureSpec); 470dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 471dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 472dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 473dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 474dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private void onMeasureForTiles(int widthMeasureSpec) { 475dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int width = MeasureSpec.getSize(widthMeasureSpec); 476dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 477dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childCount = getChildCount(); 478dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (childCount == 0) { 479dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Just in case... 480dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee setMeasuredDimension(width, 0); 481dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return; 482dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 483dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 484dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 1. Calculate image size. 485dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // = ([total width] - [total padding]) / [child count] 486dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 487dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 2. Set it to width/height of each children. 488dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // If we have a remainder, some tiles will have 1 pixel larger width than its height. 489dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 490dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // 3. Set the dimensions of itself. 491dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Let width = given width. 492dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Let height = image size + bottom paddding. 493dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 494d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final int totalPaddingsInPixels = (mColumnCount - 1) * mPaddingInPixels 495d99993213962df64c9d76005df86c2fb83fca074Yorke Lee + mRowPaddingStart + mRowPaddingEnd; 496dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 497dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Preferred width / height for images (excluding the padding). 498dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // The actual width may be 1 pixel larger than this if we have a remainder. 499dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int imageSize = (width - totalPaddingsInPixels) / mColumnCount; 500dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int remainder = width - (imageSize * mColumnCount) - totalPaddingsInPixels; 501dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 502dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee for (int i = 0; i < childCount; i++) { 503dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final View child = getChildAt(i); 504dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee final int childWidth = imageSize + child.getPaddingRight() 505dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Compensate for the remainder 506dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee + (i < remainder ? 1 : 0); 507d99993213962df64c9d76005df86c2fb83fca074Yorke Lee final int childHeight = imageSize; 508dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee child.measure( 509dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), 510dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY) 511dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee ); 512dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 513d99993213962df64c9d76005df86c2fb83fca074Yorke Lee setMeasuredDimension(width, imageSize + getPaddingTop() + getPaddingBottom()); 514dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 515dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 516dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 517dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected static class ViewTypes { 518d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int COUNT = 2; 519d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int FREQUENT = 0; 520d99993213962df64c9d76005df86c2fb83fca074Yorke Lee public static final int TOP = 1; 521dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 522dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee} 523