163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng/* 263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Copyright (C) 2011 The Android Open Source Project 363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * you may not use this file except in compliance with the License. 663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * You may obtain a copy of the License at 763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 1063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Unless required by applicable law or agreed to in writing, software 1163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 1263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * See the License for the specific language governing permissions and 1463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * limitations under the License. 1563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 1663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengpackage com.android.contacts.common.list; 1763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 1863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.content.ContentUris; 1963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.content.Context; 2063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.content.res.Resources; 2163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.database.Cursor; 2263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.graphics.drawable.Drawable; 2363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.net.Uri; 2463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.provider.ContactsContract.Contacts; 2563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.view.View; 2663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.view.ViewGroup; 2763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.widget.BaseAdapter; 2863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport android.widget.FrameLayout; 293c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwellimport android.widget.TextView; 3063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 3163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.ContactPhotoManager; 3263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.ContactPresenceIconUtil; 3363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.ContactStatusUtil; 3463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.ContactTileLoaderFactory; 3563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.MoreContactUtils; 3663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport com.android.contacts.common.R; 3776e0b32755662d2b2a33965629e7baa6bf3964bdBrian Attwellimport com.android.contacts.common.util.ViewUtil; 3863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 3963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengimport java.util.ArrayList; 4063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 4163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng/** 4263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Arranges contacts favorites according to provided {@link DisplayType}. 4363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Also allows for a configurable number of columns and {@link DisplayType} 4463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 4563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Chengpublic class ContactTileAdapter extends BaseAdapter { 4663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private static final String TAG = ContactTileAdapter.class.getSimpleName(); 4763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 4863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private DisplayType mDisplayType; 4963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private ContactTileView.Listener mListener; 5063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private Context mContext; 5163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private Resources mResources; 5263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected Cursor mContactCursor = null; 5363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private ContactPhotoManager mPhotoManager; 5463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mNumFrequents; 5563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 5663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 5763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Index of the first NON starred contact in the {@link Cursor} 5863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Only valid when {@link DisplayType#STREQUENT} is true 5963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 6063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private int mDividerPosition; 6163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mColumnCount; 6263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private int mStarredIndex; 6363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 6463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mIdIndex; 6563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mLookupIndex; 6663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mPhotoUriIndex; 6763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mNameIndex; 6863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mPresenceIndex; 6963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int mStatusIndex; 7063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 7163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private boolean mIsQuickContactEnabled = false; 7263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private final int mPaddingInPixels; 73fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell private final int mWhitespaceStartEnd; 7463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 7563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 7663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Configures the adapter to filter and display contacts using different view types. 7763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * TODO: Create Uris to support getting Starred_only and Frequent_only cursors. 7863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 7963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public enum DisplayType { 8063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 8163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Displays a mixed view type of starred and frequent contacts 8263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 8363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng STREQUENT, 8463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 8563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 8663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Display only starred contacts 8763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 8863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng STARRED_ONLY, 8963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 9063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 9163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Display only most frequently contacted 9263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 9363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng FREQUENT_ONLY, 9463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 9563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 9663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Display all contacts from a group in the cursor 9763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Use {@link com.android.contacts.GroupMemberLoader} 9863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * when passing {@link Cursor} into loadFromCusor method. 9963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 10063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Group member logic has been moved into GroupMemberTileAdapter. This constant is still 10163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * needed by calling classes. 10263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 10363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng GROUP_MEMBERS 10463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 10563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 10663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public ContactTileAdapter(Context context, ContactTileView.Listener listener, int numCols, 10763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng DisplayType displayType) { 10863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mListener = listener; 10963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mContext = context; 11063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mResources = context.getResources(); 11163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mColumnCount = (displayType == DisplayType.FREQUENT_ONLY ? 1 : numCols); 11263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mDisplayType = displayType; 11363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mNumFrequents = 0; 11463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 11563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Converting padding in dips to padding in pixels 11663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mPaddingInPixels = mContext.getResources() 11763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng .getDimensionPixelSize(R.dimen.contact_tile_divider_padding); 118fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell mWhitespaceStartEnd = mContext.getResources() 119fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell .getDimensionPixelSize(R.dimen.contact_tile_start_end_whitespace); 12063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 12163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng bindColumnIndices(); 12263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 12363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 12463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void setPhotoLoader(ContactPhotoManager photoLoader) { 12563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mPhotoManager = photoLoader; 12663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 12763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 12863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void setColumnCount(int columnCount) { 12963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mColumnCount = columnCount; 13063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 13163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 13263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void setDisplayType(DisplayType displayType) { 13363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mDisplayType = displayType; 13463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 13563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 13663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void enableQuickContact(boolean enableQuickContact) { 13763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mIsQuickContactEnabled = enableQuickContact; 13863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 13963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 14063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 14163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Sets the column indices for expected {@link Cursor} 14263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * based on {@link DisplayType}. 14363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 14463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected void bindColumnIndices() { 14563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mIdIndex = ContactTileLoaderFactory.CONTACT_ID; 14663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; 14763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; 14863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mNameIndex = ContactTileLoaderFactory.DISPLAY_NAME; 14963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mStarredIndex = ContactTileLoaderFactory.STARRED; 15063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; 15163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; 15263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 15363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 15415a8f475646c8338be244f65771e560e4875acddJay Shrauner private static boolean cursorIsValid(Cursor cursor) { 15515a8f475646c8338be244f65771e560e4875acddJay Shrauner return cursor != null && !cursor.isClosed(); 15615a8f475646c8338be244f65771e560e4875acddJay Shrauner } 15715a8f475646c8338be244f65771e560e4875acddJay Shrauner 15863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 15963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Gets the number of frequents from the passed in cursor. 16063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 16163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * This methods is needed so the GroupMemberTileAdapter can override this. 16263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 16363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * @param cursor The cursor to get number of frequents from. 16463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 16563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected void saveNumFrequentsFromCursor(Cursor cursor) { 16663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 16763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // count the number of frequents 16863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mDisplayType) { 16963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STARRED_ONLY: 17063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mNumFrequents = 0; 17163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 17263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STREQUENT: 17315a8f475646c8338be244f65771e560e4875acddJay Shrauner mNumFrequents = cursorIsValid(cursor) ? 17415a8f475646c8338be244f65771e560e4875acddJay Shrauner cursor.getCount() - mDividerPosition : 0; 17563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 17663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case FREQUENT_ONLY: 17715a8f475646c8338be244f65771e560e4875acddJay Shrauner mNumFrequents = cursorIsValid(cursor) ? cursor.getCount() : 0; 17863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 17963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 18063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalArgumentException("Unrecognized DisplayType " + mDisplayType); 18163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 18263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 18363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 18463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 18563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Creates {@link ContactTileView}s for each item in {@link Cursor}. 18663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 18763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Else use {@link ContactTileLoaderFactory} 18863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 18963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void setContactCursor(Cursor cursor) { 19063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mContactCursor = cursor; 19163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mDividerPosition = getDividerPosition(cursor); 19263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 19363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng saveNumFrequentsFromCursor(cursor); 19463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 19563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // cause a refresh of any views that rely on this data 19663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng notifyDataSetChanged(); 19763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 19863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 19963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 20063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Iterates over the {@link Cursor} 20163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns position of the first NON Starred Contact 20263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns -1 if {@link DisplayType#STARRED_ONLY} 20363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns 0 if {@link DisplayType#FREQUENT_ONLY} 20463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 20563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int getDividerPosition(Cursor cursor) { 20663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mDisplayType) { 20763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STREQUENT: 20815a8f475646c8338be244f65771e560e4875acddJay Shrauner if (!cursorIsValid(cursor)) { 20915a8f475646c8338be244f65771e560e4875acddJay Shrauner return 0; 21015a8f475646c8338be244f65771e560e4875acddJay Shrauner } 21163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng cursor.moveToPosition(-1); 21263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng while (cursor.moveToNext()) { 21363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (cursor.getInt(mStarredIndex) == 0) { 21463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return cursor.getPosition(); 21563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 21663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 21715a8f475646c8338be244f65771e560e4875acddJay Shrauner 21815a8f475646c8338be244f65771e560e4875acddJay Shrauner // There are not NON Starred contacts in cursor 21915a8f475646c8338be244f65771e560e4875acddJay Shrauner // Set divider positon to end 22015a8f475646c8338be244f65771e560e4875acddJay Shrauner return cursor.getCount(); 22163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STARRED_ONLY: 22263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // There is no divider 22363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return -1; 22463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case FREQUENT_ONLY: 22563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Divider is first 22663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return 0; 22763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 22863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalStateException("Unrecognized DisplayType " + mDisplayType); 22963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 23063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 23163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 23263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected ContactEntry createContactEntryFromCursor(Cursor cursor, int position) { 23363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // If the loader was canceled we will be given a null cursor. 23463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // In that case, show an empty list of contacts. 23515a8f475646c8338be244f65771e560e4875acddJay Shrauner if (!cursorIsValid(cursor) || cursor.getCount() <= position) { 23615a8f475646c8338be244f65771e560e4875acddJay Shrauner return null; 23715a8f475646c8338be244f65771e560e4875acddJay Shrauner } 23863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 23963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng cursor.moveToPosition(position); 24063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng long id = cursor.getLong(mIdIndex); 24163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng String photoUri = cursor.getString(mPhotoUriIndex); 24263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng String lookupKey = cursor.getString(mLookupIndex); 24363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 24463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ContactEntry contact = new ContactEntry(); 24563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng String name = cursor.getString(mNameIndex); 246d5b66d89be3117a04cf54ccdb02d704b1d934351Brandon Maxwell contact.namePrimary = (name != null) ? name : mResources.getString(R.string.missing_name); 24763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contact.status = cursor.getString(mStatusIndex); 24863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); 2496084726fbdda78bdb16e2d4cc1c3b81c84fd5da1Yorke Lee contact.lookupKey = lookupKey; 2506084726fbdda78bdb16e2d4cc1c3b81c84fd5da1Yorke Lee contact.lookupUri = ContentUris.withAppendedId( 25163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), id); 2527c1a3efb470d5dcd978f5a1b494687bedc29fa10Christine Chen contact.isFavorite = cursor.getInt(mStarredIndex) > 0; 25363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 2542a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell // Set presence icon and status message 2552a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell Drawable icon = null; 2562a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell int presence = 0; 2572a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell if (!cursor.isNull(mPresenceIndex)) { 2582a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell presence = cursor.getInt(mPresenceIndex); 2592a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell icon = ContactPresenceIconUtil.getPresenceIcon(mContext, presence); 2602a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell } 2612a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell contact.presenceIcon = icon; 26263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 2632a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell String statusMessage = null; 2642a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell if (mStatusIndex != 0 && !cursor.isNull(mStatusIndex)) { 2652a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell statusMessage = cursor.getString(mStatusIndex); 26663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 2672a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell // If there is no status message from the contact, but there was a presence value, 2682a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell // then use the default status message string 2692a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell if (statusMessage == null && presence != 0) { 2702a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell statusMessage = ContactStatusUtil.getStatusString(mContext, presence); 2712a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell } 2722a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell contact.status = statusMessage; 27363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 27463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return contact; 27563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 27663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 27763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 27863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns the number of frequents that will be displayed in the list. 27963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 28063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getNumFrequents() { 28163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return mNumFrequents; 28263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 28363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 28463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 28563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getCount() { 28615a8f475646c8338be244f65771e560e4875acddJay Shrauner if (!cursorIsValid(mContactCursor)) { 28763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return 0; 28863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 28963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 29063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mDisplayType) { 29163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STARRED_ONLY: 29263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return getRowCount(mContactCursor.getCount()); 29363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STREQUENT: 29463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Takes numbers of rows the Starred Contacts Occupy 29563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng int starredRowCount = getRowCount(mDividerPosition); 29663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 29763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Compute the frequent row count which is 1 plus the number of frequents 29863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // (to account for the divider) or 0 if there are no frequents. 29963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng int frequentRowCount = mNumFrequents == 0 ? 0 : mNumFrequents + 1; 30063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 30163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Return the number of starred plus frequent rows 30263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return starredRowCount + frequentRowCount; 30363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case FREQUENT_ONLY: 30463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Number of frequent contacts 30563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return mContactCursor.getCount(); 30663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 30763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalArgumentException("Unrecognized DisplayType " + mDisplayType); 30863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 30963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 31063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 31163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 31263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns the number of rows required to show the provided number of entries 31363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * with the current number of columns. 31463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 31563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected int getRowCount(int entryCount) { 31663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return entryCount == 0 ? 0 : ((entryCount - 1) / mColumnCount) + 1; 31763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 31863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 31963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getColumnCount() { 32063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return mColumnCount; 32163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 32263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 32363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 32463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns an ArrayList of the {@link ContactEntry}s that are to appear 32563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * on the row for the given position. 32663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 32763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 32863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public ArrayList<ContactEntry> getItem(int position) { 32963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ArrayList<ContactEntry> resultList = new ArrayList<ContactEntry>(mColumnCount); 33063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng int contactIndex = position * mColumnCount; 33163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 33263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mDisplayType) { 33363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case FREQUENT_ONLY: 33463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng resultList.add(createContactEntryFromCursor(mContactCursor, position)); 33563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 33663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STARRED_ONLY: 33763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng for (int columnCounter = 0; columnCounter < mColumnCount; columnCounter++) { 33863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex)); 33963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactIndex++; 34063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 34163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 34263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STREQUENT: 34363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (position < getRowCount(mDividerPosition)) { 34463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng for (int columnCounter = 0; columnCounter < mColumnCount && 34563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactIndex != mDividerPosition; columnCounter++) { 34663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex)); 34763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactIndex++; 34863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 34963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } else { 35063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /* 35163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Current position minus how many rows are before the divider and 35263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Minus 1 for the divider itself provides the relative index of the frequent 35363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * contact being displayed. Then add the dividerPostion to give the offset 35463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * into the contacts cursor to get the absoulte index. 35563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 35663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactIndex = position - getRowCount(mDividerPosition) - 1 + mDividerPosition; 35763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex)); 35863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 35963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 36063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 36163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalStateException("Unrecognized DisplayType " + mDisplayType); 36263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 36363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return resultList; 36463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 36563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 36663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 36763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public long getItemId(int position) { 36863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // As we show several selectable items for each ListView row, 36963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // we can not determine a stable id. But as we don't rely on ListView's selection, 37063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // this should not be a problem. 37163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return position; 37263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 37363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 37463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 37563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public boolean areAllItemsEnabled() { 3762a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell return (mDisplayType != DisplayType.STREQUENT); 37763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 37863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 37963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 38063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public boolean isEnabled(int position) { 38163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return position != getRowCount(mDividerPosition); 38263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 38363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 38463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 38563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public View getView(int position, View convertView, ViewGroup parent) { 38663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng int itemViewType = getItemViewType(position); 38763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 38863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (itemViewType == ViewTypes.DIVIDER) { 38963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Checking For Divider First so not to cast convertView 3903c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell final TextView textView = (TextView) (convertView == null ? getDivider() : convertView); 3913c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell setDividerPadding(textView, position == 0); 3923c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell return textView; 39363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 39463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 39563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ContactTileRow contactTileRowView = (ContactTileRow) convertView; 39663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ArrayList<ContactEntry> contactList = getItem(position); 39763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 39863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (contactTileRowView == null) { 39963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Creating new row if needed 40063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTileRowView = new ContactTileRow(mContext, itemViewType); 40163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 40263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 40363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTileRowView.configureRow(contactList, position == getCount() - 1); 40463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return contactTileRowView; 40563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 40663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 40763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 40863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Divider uses a list_seperator.xml along with text to denote 40963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * the most frequently contacted contacts. 41063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 4113c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell private TextView getDivider() { 4122a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell return MoreContactUtils.createHeaderView(mContext, R.string.favoritesFrequentContacted); 41363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 41463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 4153c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell private void setDividerPadding(TextView headerTextView, boolean isFirstRow) { 4163c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell MoreContactUtils.setHeaderViewBottomPadding(mContext, headerTextView, isFirstRow); 4173c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell } 4183c4e8501b8fe4a6f508a256fd133004e1f1936a4Brian Attwell 41963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private int getLayoutResourceId(int viewType) { 42063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (viewType) { 42163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.STARRED: 42263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return mIsQuickContactEnabled ? 42363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng R.layout.contact_tile_starred_quick_contact : R.layout.contact_tile_starred; 42463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.FREQUENT: 4252a913bd7024f2ccd0e2649c49d1442e9167f9039Brian Attwell return R.layout.contact_tile_frequent; 42663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 42763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalArgumentException("Unrecognized viewType " + viewType); 42863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 42963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 43063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 43163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getViewTypeCount() { 43263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.COUNT; 43363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 43463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 43563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 43663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getItemViewType(int position) { 43763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /* 43863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns view type based on {@link DisplayType}. 43963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * {@link DisplayType#STARRED_ONLY} and {@link DisplayType#GROUP_MEMBERS} 44063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * are {@link ViewTypes#STARRED}. 44163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * {@link DisplayType#FREQUENT_ONLY} is {@link ViewTypes#FREQUENT}. 44263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * {@link DisplayType#STREQUENT} mixes both {@link ViewTypes} 44363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * and also adds in {@link ViewTypes#DIVIDER}. 44463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 44563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mDisplayType) { 44663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STREQUENT: 44763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (position < getRowCount(mDividerPosition)) { 44863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.STARRED; 44963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } else if (position == getRowCount(mDividerPosition)) { 45063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.DIVIDER; 45163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } else { 45263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.FREQUENT; 45363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 45463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case STARRED_ONLY: 45563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.STARRED; 45663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case FREQUENT_ONLY: 45763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return ViewTypes.FREQUENT; 45863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 45963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng throw new IllegalStateException("Unrecognized DisplayType " + mDisplayType); 46063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 46163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 46263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 46363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 46463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Returns the "frequent header" position. Only available when STREQUENT or 46563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * STREQUENT_PHONE_ONLY is used for its display type. 46663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 46763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public int getFrequentHeaderPosition() { 46863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return getRowCount(mDividerPosition); 46963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 47063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 47163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 47263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Acts as a row item composed of {@link ContactTileView} 47363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * 47463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * TODO: FREQUENT doesn't really need it. Just let {@link #getView} return 47563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 47663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private class ContactTileRow extends FrameLayout { 47763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private int mItemViewType; 47863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private int mLayoutResId; 47963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 48063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public ContactTileRow(Context context, int itemViewType) { 48163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng super(context); 48263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mItemViewType = itemViewType; 48363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng mLayoutResId = getLayoutResourceId(mItemViewType); 48474caac49e59c78f28639b83b9cce71e802a78406Chiao Cheng 48574caac49e59c78f28639b83b9cce71e802a78406Chiao Cheng // Remove row (but not children) from accessibility node tree. 48674caac49e59c78f28639b83b9cce71e802a78406Chiao Cheng setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); 48763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 48863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 48963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng /** 49063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng * Configures the row to add {@link ContactEntry}s information to the views 49163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng */ 49263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public void configureRow(ArrayList<ContactEntry> list, boolean isLastRow) { 49363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng int columnCount = mItemViewType == ViewTypes.FREQUENT ? 1 : mColumnCount; 49463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 49563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Adding tiles to row and filling in contact information 49663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng for (int columnCounter = 0; columnCounter < columnCount; columnCounter++) { 49763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ContactEntry entry = 49863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng columnCounter < list.size() ? list.get(columnCounter) : null; 49963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng addTileFromEntry(entry, columnCounter, isLastRow); 50063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 50163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 50263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 50363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private void addTileFromEntry(ContactEntry entry, int childIndex, boolean isLastRow) { 50463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final ContactTileView contactTile; 50563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 50663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (getChildCount() <= childIndex) { 50763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile = (ContactTileView) inflate(mContext, mLayoutResId, null); 50863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Note: the layoutparam set here is only actually used for FREQUENT. 50963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // We override onMeasure() for STARRED and we don't care the layout param there. 51063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng Resources resources = mContext.getResources(); 51163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( 512440a8fb48d25b4281bd4b00ca5070da59129be14Brian Attwell ViewGroup.LayoutParams.MATCH_PARENT, 51363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ViewGroup.LayoutParams.WRAP_CONTENT); 51463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng params.setMargins( 515fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell mWhitespaceStartEnd, 51663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 0, 517fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell mWhitespaceStartEnd, 51863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 0); 51963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile.setLayoutParams(params); 52063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile.setPhotoManager(mPhotoManager); 52163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile.setListener(mListener); 52263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng addView(contactTile); 52363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } else { 52463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile = (ContactTileView) getChildAt(childIndex); 52563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 52663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile.loadFromContact(entry); 52763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 52863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mItemViewType) { 52963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.STARRED: 530d6371d642f898ad455eb12719adc0a1123009481Brian Attwell // Set padding between tiles. Divide mPaddingInPixels between left and right 531d6371d642f898ad455eb12719adc0a1123009481Brian Attwell // tiles as evenly as possible. 532d6371d642f898ad455eb12719adc0a1123009481Brian Attwell contactTile.setPaddingRelative( 533fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell (mPaddingInPixels + 1) / 2, 0, 534fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell mPaddingInPixels 535d6371d642f898ad455eb12719adc0a1123009481Brian Attwell / 2, 0); 53663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 53763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.FREQUENT: 53863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng contactTile.setHorizontalDividerVisibility( 53963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng isLastRow ? View.GONE : View.VISIBLE); 54063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 54163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 54263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng break; 54363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 54463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 54563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 54663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 54763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 54863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mItemViewType) { 54963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.STARRED: 55063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng onLayoutForTiles(); 55163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return; 55263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 55363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng super.onLayout(changed, left, top, right, bottom); 55463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return; 55563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 55663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 55763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 55863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private void onLayoutForTiles() { 55963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final int count = getChildCount(); 56063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 561fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell // Amount of margin needed on the left is based on difference between offset and padding 562fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell int childLeft = mWhitespaceStartEnd - (mPaddingInPixels + 1) / 2; 563fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell 56463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Just line up children horizontally. 56563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng for (int i = 0; i < count; i++) { 56676e0b32755662d2b2a33965629e7baa6bf3964bdBrian Attwell final int rtlAdjustedIndex = ViewUtil.isViewLayoutRtl(this) ? count - i - 1 : i; 56746027b7f219f30e1d413639caca990cb9d8aec64Brian Attwell final View child = getChildAt(rtlAdjustedIndex); 56863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 56963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Note MeasuredWidth includes the padding. 57063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final int childWidth = child.getMeasuredWidth(); 57163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); 57263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng childLeft += childWidth; 57363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 57463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 57563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 57663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng @Override 57763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 57863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng switch (mItemViewType) { 57963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng case ViewTypes.STARRED: 58063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng onMeasureForTiles(widthMeasureSpec); 58163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return; 58263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng default: 58363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng super.onMeasure(widthMeasureSpec, heightMeasureSpec); 58463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return; 58563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 58663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 58763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 58863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng private void onMeasureForTiles(int widthMeasureSpec) { 58963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final int width = MeasureSpec.getSize(widthMeasureSpec); 59063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 59163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final int childCount = getChildCount(); 59263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng if (childCount == 0) { 59363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Just in case... 59463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng setMeasuredDimension(width, 0); 59563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng return; 59663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 59763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 59863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // 1. Calculate image size. 599fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell // = ([total width] - [total whitespace]) / [child count] 60063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // 60163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // 2. Set it to width/height of each children. 60263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // If we have a remainder, some tiles will have 1 pixel larger width than its height. 60363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // 60463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // 3. Set the dimensions of itself. 60563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Let width = given width. 6066ee0728b5844ae60adb0d27d5f9b54d9720a11a0Brian Attwell // Let height = wrap content. 60763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 608fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell final int totalWhitespaceInPixels = (mColumnCount - 1) * mPaddingInPixels 609fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell + mWhitespaceStartEnd * 2; 61063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 61163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Preferred width / height for images (excluding the padding). 61263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // The actual width may be 1 pixel larger than this if we have a remainder. 613fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell final int imageSize = (width - totalWhitespaceInPixels) / mColumnCount; 614fcf62ed127081833443eb13eb9e17aaf158f441aBrian Attwell final int remainder = width - (imageSize * mColumnCount) - totalWhitespaceInPixels; 61563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 61663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng for (int i = 0; i < childCount; i++) { 61763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng final View child = getChildAt(i); 6186ee0728b5844ae60adb0d27d5f9b54d9720a11a0Brian Attwell final int childWidth = imageSize + child.getPaddingRight() + child.getPaddingLeft() 61963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng // Compensate for the remainder 62063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng + (i < remainder ? 1 : 0); 6216ee0728b5844ae60adb0d27d5f9b54d9720a11a0Brian Attwell 62263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng child.measure( 62363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), 6246ee0728b5844ae60adb0d27d5f9b54d9720a11a0Brian Attwell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) 62563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng ); 62663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 6276ee0728b5844ae60adb0d27d5f9b54d9720a11a0Brian Attwell setMeasuredDimension(width, getChildAt(0).getMeasuredHeight()); 62863ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 62963ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 63063ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng 63163ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng protected static class ViewTypes { 63263ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public static final int COUNT = 4; 63363ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public static final int STARRED = 0; 63463ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public static final int DIVIDER = 1; 63563ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng public static final int FREQUENT = 2; 63663ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng } 63763ac534dcf60e9a6c651ef2434557bec922b9a7dChiao Cheng} 638