Allows variable number of ContactTile columns

Change-Id: I0d8fb22407f5fe45963ca4533c37fc9fd34119e5
diff --git a/src/com/android/contacts/StrequentMetaDataLoader.java b/src/com/android/contacts/StrequentMetaDataLoader.java
index 203b25f..d567c44 100644
--- a/src/com/android/contacts/StrequentMetaDataLoader.java
+++ b/src/com/android/contacts/StrequentMetaDataLoader.java
@@ -28,14 +28,14 @@
     public final static int DISPLAY_NAME = 1;
     public final static int STARRED = 2;
     public final static int PHOTO_URI = 3;
-    public final static int PHOTO_ID = 4;
+    public final static int LOOKUP_KEY = 4;
 
     private static final String[] COLUMNS = new String[] {
         Contacts._ID,
         Contacts.DISPLAY_NAME,
         Contacts.STARRED,
         Contacts.PHOTO_URI,
-        Contacts.PHOTO_ID
+        Contacts.LOOKUP_KEY
     };
 
     public StrequentMetaDataLoader(Context context) {
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
new file mode 100644
index 0000000..dbfa030
--- /dev/null
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+import com.android.contacts.StrequentMetaDataLoader;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+
+/**
+ * Arranges contacts in {@link StrequentFragment} (aka favorites) according to if the contact
+ * is starred or not. Also shows a configurable but fixed number of contacts per row.
+ */
+public class ContactTileAdapter extends BaseAdapter {
+    private static final String TAG = "ContactTileAdapter";
+
+    private ArrayList<StrequentEntry> mAllEntries;
+    private Listener mListener;
+    private int mMostFrequentCount;
+    private int mStarredCount;
+    private Context mContext;
+    private int mColumnCount;
+    private ContactPhotoManager mPhotoManager;
+
+    public ContactTileAdapter(Context context, Listener listener, int numCols) {
+        mListener = listener;
+        mContext = context;
+        mColumnCount = numCols;
+        mPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
+    }
+
+    public void setCursor(Cursor cursor){
+        populateStrequentEntries(cursor);
+    }
+
+    private void populateStrequentEntries(Cursor cursor) {
+        mAllEntries = new ArrayList<StrequentEntry>();
+        mMostFrequentCount = mStarredCount = 0;
+
+        // If the loader was canceled we will be given a null cursor.
+        // In that case, show an empty list of contacts.
+        if (cursor != null) {
+            while (cursor.moveToNext()) {
+                StrequentEntry contact = new StrequentEntry();
+
+                long id = cursor.getLong(StrequentMetaDataLoader.CONTACT_ID);
+                String lookupKey = cursor.getString(StrequentMetaDataLoader.LOOKUP_KEY);
+                String photoUri = cursor.getString(StrequentMetaDataLoader.PHOTO_URI);
+
+                if (photoUri != null) contact.photoUri = Uri.parse(photoUri);
+                else contact.photoUri = null;
+
+                contact.lookupKey = ContentUris.withAppendedId(
+                        Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), id);
+                contact.name = cursor.getString(StrequentMetaDataLoader.DISPLAY_NAME);
+
+                if (cursor.getInt(StrequentMetaDataLoader.STARRED) == 1) mStarredCount++;
+                else mMostFrequentCount++;
+
+                mAllEntries.add(contact);
+            }
+        }
+        notifyDataSetChanged();
+    }
+
+    @Override
+    /*
+     * Doing some math to make sure number to rounded up to account
+     * for a partially filled row, if necessary.
+     */
+    public int getCount() {
+        return ((mAllEntries.size() - 1) / mColumnCount) + 1;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return mAllEntries.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 1;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        int rowIndex = position * mColumnCount;
+        ContactTileRow contactTileRowView = (ContactTileRow) convertView;
+
+        if (contactTileRowView == null) {
+            contactTileRowView = new ContactTileRow(mContext);
+        }
+
+        for (int columnCounter = 0; columnCounter < mColumnCount; columnCounter++) {
+            int contactIndex = rowIndex + columnCounter;
+
+            if (contactIndex >= mAllEntries.size()) {
+                contactTileRowView.removeViewAt(columnCounter);
+            } else {
+                contactTileRowView.addTileFromEntry(mAllEntries.get(contactIndex), columnCounter);
+            }
+        }
+        return contactTileRowView;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 1;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return 1;
+    }
+
+    /**
+     * Acts as a row item composed of {@link ContactTileView}
+     */
+    private class ContactTileRow extends LinearLayout implements OnClickListener {
+
+        public ContactTileRow(Context context) {
+            super(context);
+        }
+
+        public void addTileFromEntry(StrequentEntry entry, int tileIndex) {
+            ContactTileView contactTile;
+
+            if (getChildCount() <= tileIndex) {
+                contactTile = (ContactTileView)
+                        inflate(mContext, R.layout.contact_tile_regular, null);
+
+                contactTile.setContactPhotoManager(mPhotoManager);
+                contactTile.setOnClickListener(this);
+                addView(contactTile);
+            } else {
+                contactTile = (ContactTileView) getChildAt(tileIndex);
+            }
+            contactTile.loadFromContact(entry);
+        }
+
+        @Override
+        public void onClick(View v) {
+            mListener.onContactSelected(((ContactTileView) v).getLookupUri());
+        }
+    }
+
+    /**
+     * Class to hold contact information
+     */
+    public static class StrequentEntry {
+        public Uri photoUri;
+        public String name;
+        public Uri lookupKey;
+    }
+
+    public interface Listener {
+        public void onContactSelected(Uri contactUri);
+    }
+}
diff --git a/src/com/android/contacts/list/ContactTileView.java b/src/com/android/contacts/list/ContactTileView.java
new file mode 100644
index 0000000..06dbc1d
--- /dev/null
+++ b/src/com/android/contacts/list/ContactTileView.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+import com.android.contacts.list.ContactTileAdapter.StrequentEntry;
+
+import android.content.Context;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/*
+ * A ContactTile displays the contact's picture overlayed with their name
+ */
+public class ContactTileView extends RelativeLayout {
+    private final static String TAG = "ContactTileView";
+
+    private Uri mLookupUri;
+    private ImageView mPhoto;
+    private TextView mName;
+    private ContactPhotoManager mPhotoManager;
+
+    public ContactTileView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mName = (TextView) findViewById(R.id.contact_tile_name);
+        mPhoto = (ImageView) findViewById(R.id.contact_tile_image);
+    }
+
+    public void loadFromContact(StrequentEntry entry) {
+        if (entry != null) {
+            mName.setText(entry.name);
+            mLookupUri = entry.lookupKey;
+
+            if (mPhotoManager != null) mPhotoManager.loadPhoto(mPhoto, entry.photoUri);
+            else Log.w(TAG, "contactPhotoManger not set");
+
+        } else {
+            Log.w(TAG, "loadFromContact received null formal");
+            throw new IllegalArgumentException();
+        }
+    }
+
+    public void setContactPhotoManager(ContactPhotoManager manager) {
+        mPhotoManager = manager;
+    }
+
+    public Uri getLookupUri() {
+        return mLookupUri;
+    }
+}
diff --git a/src/com/android/contacts/list/StrequentAdapter.java b/src/com/android/contacts/list/StrequentAdapter.java
deleted file mode 100644
index fc7a944..0000000
--- a/src/com/android/contacts/list/StrequentAdapter.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.contacts.list;
-
-import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.R;
-import com.android.contacts.StrequentMetaDataLoader;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-/**
- * Arranges contacts in {@link StrequentFragment} (aka favorites) according to if the contact
- * is starred or not. Also shows two contacts per row.
- */
-public class StrequentAdapter extends BaseAdapter implements OnClickListener {
-
-    private LayoutInflater mInflater;
-    private ArrayList<StrequentEntry> mAllEntries;
-    private ContactPhotoManager mPhotoManager;
-    private Listener mListener;
-    private int mMostFrequentCount;
-    private int mStarredCount;
-    private static final int NUMCOLS = 2;
-
-    public StrequentAdapter(Context context, Listener listener) {
-        mInflater = LayoutInflater.from(context);
-        mPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
-        mListener = listener;
-    }
-
-    public void setCursor(Cursor cursor){
-        populateStrequentEntries(cursor);
-    }
-
-    private void populateStrequentEntries(Cursor cursor) {
-        mAllEntries = new ArrayList<StrequentEntry>();
-        mMostFrequentCount = mStarredCount = 0;
-
-        // If the loader was canceled we will be given a null cursor.
-        // In that case, show an empty list of contacts.
-        if (cursor != null) {
-            while (cursor.moveToNext()) {
-                StrequentEntry contact = new StrequentEntry();
-
-                contact.id = cursor.getLong(StrequentMetaDataLoader.CONTACT_ID);
-                contact.photoId = cursor.getLong(StrequentMetaDataLoader.PHOTO_ID);
-                contact.name = cursor.getString(StrequentMetaDataLoader.DISPLAY_NAME);
-
-                // Adding Starred Contact
-                if (cursor.getInt(StrequentMetaDataLoader.STARRED) == 1) {
-                    mStarredCount++;
-                } else {
-                    mMostFrequentCount++;
-                }
-                mAllEntries.add(contact);
-            }
-        }
-        this.notifyDataSetChanged();
-    }
-
-    @Override
-    public int getCount() {
-        return mAllEntries.size() / NUMCOLS;
-    }
-
-    @Override
-    public Object getItem(int position) {
-        return mAllEntries.get(position);
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return mAllEntries.get(position).id;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        ViewHolder holder;
-        // Note: For now, every row except for the last row will have 2 columns
-        int index = position * NUMCOLS;
-
-        // Try to recycle convertView
-        if (convertView != null) {
-            holder = (ViewHolder) convertView.getTag();
-        } else {
-            // Must create new View
-            convertView = mInflater.inflate(R.layout.contact_tile_row_regular, null);
-            holder = new ViewHolder(convertView);
-
-            holder.getLayoutLeft().setOnClickListener(this);
-            holder.getLayoutRight().setOnClickListener(this);
-
-            convertView.setTag(holder);
-        }
-
-        holder.getTextLeft().setText(mAllEntries.get(index).name);
-        mPhotoManager.loadPhoto(holder.getImageLeft(), mAllEntries.get(index).photoId);
-        holder.getLayoutLeft().setTag(mAllEntries.get(index));
-
-        if (++index < mAllEntries.size()) {
-            holder.getTextRight().setText(mAllEntries.get(index).name);
-            mPhotoManager.loadPhoto(holder.mImageRight, mAllEntries.get(index).photoId);
-            holder.getLayoutRight().setTag(mAllEntries.get(index));
-        } else {
-            holder.getTextRight().setText(null);
-            holder.getImageRight().setImageBitmap(null);
-            holder.getLayoutRight().setOnClickListener(null);
-        }
-
-        return convertView;
-    }
-
-    @Override
-    public int getViewTypeCount() {
-        return 1;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return 1;
-    }
-
-    /**
-     * Class it hold views for layout to help make wonderful listview faster
-     */
-    private static class ViewHolder {
-        private TextView mTextLeft, mTextRight;
-        private ImageView mImageLeft, mImageRight;
-        private View mLayoutLeft, mLayoutRight;
-
-        public ViewHolder(View convertView){
-            // Left Column
-            mTextLeft = (TextView) convertView.findViewById(R.id.contactTile_left_name);
-            mImageLeft = (ImageView) convertView.findViewById(R.id.contactTile_left_image);
-            mLayoutLeft = convertView.findViewById(R.id.contactTile_row_left);
-
-            // Right Column
-            mTextRight = (TextView) convertView.findViewById(R.id.contactTile_right_name);
-            mImageRight = (ImageView) convertView.findViewById(R.id.contactTile_right_image);
-            mLayoutRight = convertView.findViewById(R.id.contactTile_row_right);
-        }
-
-        public TextView getTextLeft() {
-            return mTextLeft;
-        }
-
-        public void setTextLeft(TextView textLeft) {
-            this.mTextLeft = textLeft;
-        }
-
-        public TextView getTextRight() {
-            return mTextRight;
-        }
-
-        public void setTextRight(TextView textRight) {
-            this.mTextRight = textRight;
-        }
-
-        public ImageView getImageLeft() {
-            return mImageLeft;
-        }
-
-        public void setImageLeft(ImageView imageLeft) {
-            this.mImageLeft = imageLeft;
-        }
-
-        public ImageView getImageRight() {
-            return mImageRight;
-        }
-
-        public void setImageRight(ImageView imageRight) {
-            this.mImageRight = imageRight;
-        }
-
-        public View getLayoutLeft() {
-            return mLayoutLeft;
-        }
-
-        public void setLayoutLeft(View layoutLeft) {
-            this.mLayoutLeft = layoutLeft;
-        }
-
-        public View getLayoutRight() {
-            return mLayoutRight;
-        }
-
-        public void setLayoutRight(View layoutRight) {
-            this.mLayoutRight = layoutRight;
-        }
-    }
-
-    /**
-     * Class to hold contact information
-     */
-    private static class StrequentEntry {
-        public long id;
-        public long photoId;
-        public String name;
-    }
-
-    @Override
-    public void onClick(View v) {
-        StrequentEntry entry = (StrequentEntry)v.getTag();
-        Uri data = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(entry.id));
-        mListener.onContactSelected(data);
-    }
-
-    public interface Listener {
-        public void onContactSelected(Uri contactUri);
-    }
-}
diff --git a/src/com/android/contacts/list/StrequentContactListAdapter.java b/src/com/android/contacts/list/StrequentContactListAdapter.java
deleted file mode 100644
index 12c56f3..0000000
--- a/src/com/android/contacts/list/StrequentContactListAdapter.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.contacts.list;
-
-import com.android.contacts.R;
-import com.android.contacts.util.PhoneCapabilityTester;
-
-import android.content.Context;
-import android.content.CursorLoader;
-import android.database.Cursor;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.widget.ListView;
-import android.widget.TextView;
-
-/**
- * A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type loading
- * a combination of starred and frequently contacted.
- */
-public class StrequentContactListAdapter extends ContactListAdapter {
-
-    private int mFrequentSeparatorPos = ListView.INVALID_POSITION;
-    private TextView mSeparatorView;
-    private OnClickListener mCallButtonListener;
-    private int mCallButtonId;
-    private boolean mStarredContactsIncluded;
-    private boolean mFrequentlyContactedContactsIncluded;
-    private boolean mIsPhone;
-
-    public StrequentContactListAdapter(Context context, int callButtonId) {
-        super(context);
-        mCallButtonId = callButtonId;
-    }
-
-    public void setCallButtonListener(OnClickListener callButtonListener) {
-        mCallButtonListener = callButtonListener;
-    }
-
-    public void setStarredContactsIncluded(boolean flag) {
-        mStarredContactsIncluded = flag;
-    }
-
-    public void setFrequentlyContactedContactsIncluded(boolean flag) {
-        mFrequentlyContactedContactsIncluded = flag;
-    }
-
-    @Override
-    public void configureLoader(CursorLoader loader, long directoryId) {
-        String sortOrder = getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY
-                ? Contacts.SORT_KEY_PRIMARY
-                : Contacts.SORT_KEY_ALTERNATIVE;
-        if (mStarredContactsIncluded && mFrequentlyContactedContactsIncluded) {
-            loader.setUri(Contacts.CONTENT_STREQUENT_URI);
-        } else if (mStarredContactsIncluded) {
-            loader.setUri(Contacts.CONTENT_URI);
-            loader.setSelection(Contacts.STARRED + "!=0");
-        } else if (mFrequentlyContactedContactsIncluded) {
-            loader.setUri(Contacts.CONTENT_URI);
-            loader.setSelection(Contacts.TIMES_CONTACTED + " > 0");
-            sortOrder = Contacts.TIMES_CONTACTED + " DESC";
-        } else {
-            throw new UnsupportedOperationException("Neither StarredContactsIncluded nor "
-                    + "FrequentlyContactedContactsIncluded is set");
-        }
-
-        loader.setProjection(PROJECTION_CONTACT);
-        loader.setSortOrder(sortOrder);
-    }
-
-    @Override
-    protected void invalidate() {
-        super.invalidate();
-
-        // Sometimes the adapter is invalidated without calling changeCursor,
-        // need to reset the separator position then.
-        mFrequentSeparatorPos = ListView.INVALID_POSITION;
-        mIsPhone = PhoneCapabilityTester.isPhone(getContext());
-    }
-
-    @Override
-    public void changeCursor(int partition, Cursor cursor) {
-        super.changeCursor(partition, cursor);
-
-        // Get the split between starred and frequent items, if the mode is strequent
-        mFrequentSeparatorPos = ListView.INVALID_POSITION;
-
-        if (mStarredContactsIncluded && mFrequentlyContactedContactsIncluded) {
-            int count = 0;
-            if (cursor != null && (count = cursor.getCount()) > 0) {
-                cursor.moveToPosition(-1);
-                for (int i = 0; cursor.moveToNext(); i++) {
-                    int starred = cursor.getInt(CONTACT_STARRED_COLUMN_INDEX);
-                    if (starred == 0) {
-                        if (i > 0) {
-                            // Only add the separator when there are starred items present
-                            mFrequentSeparatorPos = i;
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public int getCount() {
-        if (mFrequentSeparatorPos == ListView.INVALID_POSITION) {
-            return super.getCount();
-        } else {
-            // Add a row for the separator
-            return super.getCount() + 1;
-        }
-    }
-
-    @Override
-    public boolean areAllItemsEnabled() {
-        return mFrequentSeparatorPos == ListView.INVALID_POSITION;
-    }
-
-    @Override
-    public boolean isEnabled(int position) {
-        return position != mFrequentSeparatorPos;
-    }
-
-    @Override
-    public Object getItem(int position) {
-        if (mFrequentSeparatorPos == ListView.INVALID_POSITION
-                || position < mFrequentSeparatorPos) {
-            return super.getItem(position);
-        } else {
-            return super.getItem(position - 1);
-        }
-    }
-
-    @Override
-    public long getItemId(int position) {
-        if (mFrequentSeparatorPos == ListView.INVALID_POSITION
-                || position < mFrequentSeparatorPos) {
-            return super.getItemId(position);
-        } else {
-            return super.getItemId(position - 1);
-        }
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        if (mFrequentSeparatorPos == ListView.INVALID_POSITION
-                || position < mFrequentSeparatorPos) {
-            return super.getItemViewType(position);
-        } else if (position == mFrequentSeparatorPos) {
-            return IGNORE_ITEM_VIEW_TYPE;
-        } else {
-            return super.getItemViewType(position - 1);
-        }
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        if (mFrequentSeparatorPos == ListView.INVALID_POSITION
-                || position < mFrequentSeparatorPos) {
-            return super.getView(position, convertView, parent);
-        } else if (position == mFrequentSeparatorPos) {
-            if (mSeparatorView == null) {
-                mSeparatorView = (TextView)LayoutInflater.from(getContext()).
-                        inflate(R.layout.list_separator, parent, false);
-                mSeparatorView.setText(R.string.favoritesFrquentSeparator);
-            }
-            return mSeparatorView;
-        } else {
-            return super.getView(position - 1, convertView, parent);
-        }
-    }
-
-    @Override
-    protected View newView(Context context, int partition, Cursor cursor, int position,
-            ViewGroup parent) {
-        ContactListItemView view = (ContactListItemView)super.newView(context, partition, cursor,
-                position, parent);
-        view.setOnCallButtonClickListener(mCallButtonListener);
-        return view;
-    }
-
-    @Override
-    protected void bindView(View itemView, int partition, Cursor cursor, int position) {
-        final ContactListItemView view = (ContactListItemView)itemView;
-
-        if (isSelectionVisible()) {
-            view.setActivated(isSelectedContact(partition, cursor));
-        }
-
-        bindName(view, cursor);
-        if (isQuickContactEnabled()) {
-            bindQuickContact(view, partition, cursor);
-        } else {
-            bindPhoto(view, partition, cursor);
-        }
-        bindPresence(view, cursor);
-
-        // Make the call button visible if requested.
-        if (mIsPhone && getHasPhoneNumber(position)) {
-            view.showCallButton(mCallButtonId, position);
-        } else {
-            view.hideCallButton();
-        }
-    }
-}
diff --git a/src/com/android/contacts/list/StrequentContactListFragment.java b/src/com/android/contacts/list/StrequentContactListFragment.java
index 47cc7be..b9a14ac 100644
--- a/src/com/android/contacts/list/StrequentContactListFragment.java
+++ b/src/com/android/contacts/list/StrequentContactListFragment.java
@@ -37,21 +37,23 @@
  * Fragment containing a list of starred contacts followed by a list of frequently contacted.
  */
 public class StrequentContactListFragment extends Fragment {
+
     public interface Listener {
         public void onContactSelected(Uri contactUri);
     }
 
     private static int LOADER_STREQUENT = 1;
+    private static final int NUM_COLS = 2;
 
     private Listener mListener;
-    private StrequentAdapter mAdapter;
+    private ContactTileAdapter mAdapter;
     private ListView mListView;
     private Context mContext;
 
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
-        mAdapter = new StrequentAdapter(getActivity(), mAdapterListener);
+        mAdapter = new ContactTileAdapter(activity, mAdapterListener, NUM_COLS);
         mContext = activity;
     }
 
@@ -97,8 +99,8 @@
         }
     };
 
-    private StrequentAdapter.Listener mAdapterListener =
-            new StrequentAdapter.Listener() {
+    private ContactTileAdapter.Listener mAdapterListener =
+            new ContactTileAdapter.Listener() {
         @Override
         public void onContactSelected(Uri contactUri) {
             if (mListener != null) {