1238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov/* 232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro * Copyright (C) 2011 The Android Open Source Project 3238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * 4238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * you may not use this file except in compliance with the License. 6238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * You may obtain a copy of the License at 7238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * 8238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * 10238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * See the License for the specific language governing permissions and 14238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * limitations under the License. 15238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov */ 16238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikovpackage com.android.contacts.list; 17238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov 1832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.app.Activity; 1932f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.app.Fragment; 2032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.app.LoaderManager; 2132f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.app.LoaderManager.LoaderCallbacks; 2232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.content.CursorLoader; 2332f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.content.Loader; 24e5d06f534d58baa27fe6b1091b9724f81fd258c9Frank Sposaroimport android.content.res.Resources; 2532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.database.Cursor; 267a700cf798a19a8452b8671f643a05336f63f611Katherine Kuanimport android.graphics.Rect; 2732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.net.Uri; 2832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.os.Bundle; 29238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikovimport android.view.LayoutInflater; 30238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikovimport android.view.View; 31238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikovimport android.view.ViewGroup; 3232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaroimport android.widget.ListView; 3337efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaroimport android.widget.TextView; 34238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov 3579a6b5d3a885bc508b4b98c92a946fe12643c444Chiao Chengimport com.android.contacts.common.ContactPhotoManager; 36c8dd78c595cfaf9766e59a2df012b16d6c05b213Chiao Chengimport com.android.contacts.common.ContactTileLoaderFactory; 37e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 38e776d0366d5bf2f93a0cd0f14e48804e564bccf2Chiao Chengimport com.android.contacts.common.list.ContactTileAdapter; 39e776d0366d5bf2f93a0cd0f14e48804e564bccf2Chiao Chengimport com.android.contacts.common.list.ContactTileView; 40e776d0366d5bf2f93a0cd0f14e48804e564bccf2Chiao Chengimport com.android.contacts.common.list.ContactTileAdapter.DisplayType; 41e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 42238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov/** 43238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov * Fragment containing a list of starred contacts followed by a list of frequently contacted. 44f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan * 45f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan * TODO: Make this an abstract class so that the favorites, frequent, and group list functionality 46f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan * can be separated out. This will make it easier to customize any of those lists if necessary 47f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan * (i.e. adding header views to the ListViews in the fragment). This work was started 48f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan * by creating {@link ContactTileFrequentFragment}. 49238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov */ 507979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaropublic class ContactTileListFragment extends Fragment { 517979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro private static final String TAG = ContactTileListFragment.class.getSimpleName(); 52b961b3b6dae6e3f1b6096631f130c38bfa33267cFrank Sposaro 5332f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public interface Listener { 544e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus void onContactSelected(Uri contactUri, Rect targetRect); 554e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus void onCallNumberDirectly(String phoneNumber); 5632f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro } 577c5286ed8ba0d7fbe3683b560f69b3a2d4ff1e2aDmitri Plotnikov 5832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro private Listener mListener; 59b961b3b6dae6e3f1b6096631f130c38bfa33267cFrank Sposaro private ContactTileAdapter mAdapter; 6037efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro private DisplayType mDisplayType; 6137efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro private TextView mEmptyView; 6232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro private ListView mListView; 635a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov 642fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu private boolean mOptionsMenuHasFrequents; 652fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 66469c6cc2226a9454bda86cd5aa95e771ab09fdb8Dmitri Plotnikov @Override 6732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public void onAttach(Activity activity) { 6832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro super.onAttach(activity); 69e5d06f534d58baa27fe6b1091b9724f81fd258c9Frank Sposaro 70e5d06f534d58baa27fe6b1091b9724f81fd258c9Frank Sposaro Resources res = getResources(); 712871d61514f014926d991e8b037828c67438e522Maurice Chu int columnCount = res.getInteger(R.integer.contact_tile_column_count_in_favorites); 72e5d06f534d58baa27fe6b1091b9724f81fd258c9Frank Sposaro 73c569acf64701828c84271a81836dfd1a404dba03Frank Sposaro mAdapter = new ContactTileAdapter(activity, mAdapterListener, 747979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro columnCount, mDisplayType); 755f34b2e20ad4a41b6dd3fd0703d59e085bffeb1cFrank Sposaro mAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); 765a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov } 775a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov 7832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 7932f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public View onCreateView(LayoutInflater inflater, ViewGroup container, 8032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro Bundle savedInstanceState) { 81f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan return inflateAndSetupView(inflater, container, savedInstanceState, 82f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan R.layout.contact_tile_list); 83f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan } 84f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan 85f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan protected View inflateAndSetupView(LayoutInflater inflater, ViewGroup container, 86f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan Bundle savedInstanceState, int layoutResourceId) { 87f7689c377caba183daa41856d01a8c1a2f7ba811Katherine Kuan View listLayout = inflater.inflate(layoutResourceId, container, false); 8837efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro 8937efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty); 9037efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list); 9137efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro 9232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro mListView.setItemsCanFocus(true); 937979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mListView.setAdapter(mAdapter); 9437efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro return listLayout; 955a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov } 965a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov 97238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov @Override 987979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro public void onStart() { 9932f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro super.onStart(); 1002871d61514f014926d991e8b037828c67438e522Maurice Chu 1012871d61514f014926d991e8b037828c67438e522Maurice Chu // initialize the loader for this display type and destroy all others 1022871d61514f014926d991e8b037828c67438e522Maurice Chu final DisplayType[] loaderTypes = mDisplayType.values(); 1032871d61514f014926d991e8b037828c67438e522Maurice Chu for (int i = 0; i < loaderTypes.length; i++) { 1042871d61514f014926d991e8b037828c67438e522Maurice Chu if (loaderTypes[i] == mDisplayType) { 1052871d61514f014926d991e8b037828c67438e522Maurice Chu getLoaderManager().initLoader(mDisplayType.ordinal(), null, 1062871d61514f014926d991e8b037828c67438e522Maurice Chu mContactTileLoaderListener); 1072871d61514f014926d991e8b037828c67438e522Maurice Chu } else { 1082871d61514f014926d991e8b037828c67438e522Maurice Chu getLoaderManager().destroyLoader(loaderTypes[i].ordinal()); 1092871d61514f014926d991e8b037828c67438e522Maurice Chu } 1102871d61514f014926d991e8b037828c67438e522Maurice Chu } 111238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov } 112238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov 1132fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu /** 1142fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu * Returns whether there are any frequents with the side effect of setting the 1152fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu * internal flag mOptionsMenuHasFrequents to the value. This should be called externally 1162fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu * by the activity that is about to prepare the options menu with the clear frequents 1172fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu * menu item. 1182fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu */ 1192fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu public boolean hasFrequents() { 1202fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu mOptionsMenuHasFrequents = internalHasFrequents(); 1212fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu return mOptionsMenuHasFrequents; 1222fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu } 1232fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 1242fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu /** 1252fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu * Returns whether there are any frequents. 1262fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu */ 1272fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu private boolean internalHasFrequents() { 1282fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu return mAdapter.getNumFrequents() > 0; 1292fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu } 1302fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 131f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro public void setColumnCount(int columnCount) { 132f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro mAdapter.setColumnCount(columnCount); 133f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro } 134f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro 135f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro public void setDisplayType(DisplayType displayType) { 1367979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mDisplayType = displayType; 1377979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mAdapter.setDisplayType(mDisplayType); 138f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro } 139f00ff8b91e6c452839bb80c195bc8616797b9a0cFrank Sposaro 1407979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro public void enableQuickContact(boolean enableQuickContact) { 1417979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mAdapter.enableQuickContact(enableQuickContact); 1429e095d2ffc4a94d2fb925d19df6db12bc2b1e124Frank Sposaro } 1439e095d2ffc4a94d2fb925d19df6db12bc2b1e124Frank Sposaro 1447979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener = 14532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro new LoaderCallbacks<Cursor>() { 1465a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov 14732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 14832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public CursorLoader onCreateLoader(int id, Bundle args) { 1497979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro switch (mDisplayType) { 1507979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro case STARRED_ONLY: 1517979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro return ContactTileLoaderFactory.createStarredLoader(getActivity()); 1527979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro case STREQUENT: 1537979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro return ContactTileLoaderFactory.createStrequentLoader(getActivity()); 1540c07935a3d838ed24db7d20df839be97fe4c625aFrank Sposaro case STREQUENT_PHONE_ONLY: 1550c07935a3d838ed24db7d20df839be97fe4c625aFrank Sposaro return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); 1567979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro case FREQUENT_ONLY: 1577979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro return ContactTileLoaderFactory.createFrequentLoader(getActivity()); 1587979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro default: 1597979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro throw new IllegalStateException( 1607979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro "Unrecognized DisplayType " + mDisplayType); 1617979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro } 1625a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov } 1635a03880a8e05de20f74d1621e5903a9c529397e3Dmitri Plotnikov 16432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 16532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1667979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro mAdapter.setContactCursor(data); 16737efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro mEmptyView.setText(getEmptyStateText()); 16837efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro mListView.setEmptyView(mEmptyView); 1692fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 1702fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu // invalidate the menu options if needed 1712fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu invalidateOptionsMenuIfNeeded(); 17232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro } 17368e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov 17432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 1757979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro public void onLoaderReset(Loader<Cursor> loader) {} 17632f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro }; 17732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro 1782fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu private boolean isOptionsMenuChanged() { 1792fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu return mOptionsMenuHasFrequents != internalHasFrequents(); 1802fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu } 1812fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 1822fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu private void invalidateOptionsMenuIfNeeded() { 1832fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu if (isOptionsMenuChanged()) { 1842fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu getActivity().invalidateOptionsMenu(); 1852fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu } 1862fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu } 1872fc4de31fe2d6a261d3eeaff69ea944a5383003eMaurice Chu 18837efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro private String getEmptyStateText() { 18937efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro String emptyText; 19037efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro switch (mDisplayType) { 19137efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro case STREQUENT: 19237efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro case STREQUENT_PHONE_ONLY: 19337efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro case STARRED_ONLY: 19437efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro emptyText = getString(R.string.listTotalAllContactsZeroStarred); 19537efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro break; 19637efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro case FREQUENT_ONLY: 19737efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro case GROUP_MEMBERS: 19837efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro emptyText = getString(R.string.noContacts); 19937efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro break; 20037efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro default: 20137efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro throw new IllegalArgumentException("Unrecognized DisplayType " + mDisplayType); 20237efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro } 20337efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro return emptyText; 20437efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro } 20537efa3aeea2e26fdee640b797efc39279500c4daFrank Sposaro 2065f34b2e20ad4a41b6dd3fd0703d59e085bffeb1cFrank Sposaro public void setListener(Listener listener) { 2075f34b2e20ad4a41b6dd3fd0703d59e085bffeb1cFrank Sposaro mListener = listener; 2085f34b2e20ad4a41b6dd3fd0703d59e085bffeb1cFrank Sposaro } 2095f34b2e20ad4a41b6dd3fd0703d59e085bffeb1cFrank Sposaro 2104e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus private ContactTileView.Listener mAdapterListener = 2114e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus new ContactTileView.Listener() { 21232f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro @Override 2137a700cf798a19a8452b8671f643a05336f63f611Katherine Kuan public void onContactSelected(Uri contactUri, Rect targetRect) { 21432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro if (mListener != null) { 2157a700cf798a19a8452b8671f643a05336f63f611Katherine Kuan mListener.onContactSelected(contactUri, targetRect); 2167c5286ed8ba0d7fbe3683b560f69b3a2d4ff1e2aDmitri Plotnikov } 2177c5286ed8ba0d7fbe3683b560f69b3a2d4ff1e2aDmitri Plotnikov } 2184e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus 2194e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus @Override 2204e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus public void onCallNumberDirectly(String phoneNumber) { 2214e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus if (mListener != null) { 2224e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus mListener.onCallNumberDirectly(phoneNumber); 2234e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus } 2244e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus } 2252f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann 2262f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann @Override 2272f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann public int getApproximateTileWidth() { 2282f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann return getView().getWidth() / mAdapter.getColumnCount(); 2292f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann } 23032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro }; 231238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov} 232