PhoneFavoriteFragment.java revision 90f40d0162e4cee5b94bf3203c059e27f6472fab
19b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa/* 29b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Copyright (C) 2011 The Android Open Source Project 39b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * 49b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); 59b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * you may not use this file except in compliance with the License. 69b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * You may obtain a copy of the License at 79b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * 89b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 99b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * 109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, 129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * See the License for the specific language governing permissions and 149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * limitations under the License. 159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawapackage com.android.contacts.list; 179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport com.android.contacts.ContactPhotoManager; 199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport com.android.contacts.ContactTileLoaderFactory; 209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport com.android.contacts.R; 217c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport com.android.contacts.interactions.ImportExportDialogFragment; 229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport com.android.contacts.preference.ContactsPreferences; 2334b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawaimport com.android.contacts.util.AccountFilterUtil; 249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.app.Activity; 269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.app.Fragment; 279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.app.LoaderManager; 289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.CursorLoader; 299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.Intent; 309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.Loader; 319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.database.Cursor; 327a700cf798a19a8452b8671f643a05336f63f611Katherine Kuanimport android.graphics.Rect; 339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.net.Uri; 349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.os.Bundle; 3590f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawaimport android.os.Handler; 3690f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawaimport android.os.Message; 377c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.provider.ContactsContract; 389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.provider.ContactsContract.Directory; 397c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.provider.Settings; 409b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.util.Log; 419b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.LayoutInflater; 427c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.Menu; 437c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.MenuInflater; 447c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.MenuItem; 459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.View; 469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.View.OnClickListener; 479b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.ViewGroup; 481dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawaimport android.widget.AbsListView; 499b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.AdapterView; 509b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 5134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawaimport android.widget.FrameLayout; 529b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.ListView; 539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.TextView; 549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa/** 569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Fragment for Phone UI's favorite screen. 579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * 589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * This fragment contains three kinds of contacts in one screen: "starred", "frequent", and "all" 599b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * contacts. To show them at once, this merges results from {@link ContactTileAdapter} and 609b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * {@link PhoneNumberListAdapter} into one unified list using {@link PhoneFavoriteMergedAdapter}. 619b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * A contact filter header is also inserted between those adapters' results. 629b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 63091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawapublic class PhoneFavoriteFragment extends Fragment implements OnItemClickListener { 649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private static final String TAG = PhoneFavoriteFragment.class.getSimpleName(); 659b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private static final boolean DEBUG = false; 669b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa /** 689b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Used with LoaderManager. 699b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private static int LOADER_ID_CONTACT_TILE = 1; 719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private static int LOADER_ID_ALL_CONTACTS = 2; 729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private static final String KEY_FILTER = "filter"; 749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 7534b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa private static final int REQUEST_CODE_ACCOUNT_FILTER = 1; 7634b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa 779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public interface Listener { 789b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onContactSelected(Uri contactUri); 794e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus public void onCallNumberDirectly(String phoneNumber); 809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public CursorLoader onCreateLoader(int id, Bundle args) { 859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); 869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); 879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 889b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 899b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 909b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 919b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); 929b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mContactTileAdapter.setContactCursor(data); 939b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (mAllContactsForceReload) { 959b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsAdapter.onDataReload(); 969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // Use restartLoader() to make LoaderManager to load the section again. 979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa getLoaderManager().restartLoader( 989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener); 999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } else if (!mAllContactsLoaderStarted) { 1009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // Load "all" contacts if not loaded yet. 1019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa getLoaderManager().initLoader( 1029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener); 1039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsForceReload = false; 1059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsLoaderStarted = true; 1069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // Show the filter header with "loading" state. 1089b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa updateFilterHeaderView(); 10934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa mAccountFilterHeader.setVisibility(View.VISIBLE); 1109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onLoaderReset(Loader<Cursor> loader) { 1149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); 1159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private class AllContactsLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 1199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public Loader<Cursor> onCreateLoader(int id, Bundle args) { 1219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onCreateLoader"); 1229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa CursorLoader loader = new CursorLoader(getActivity(), null, null, null, null, null); 1239b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsAdapter.configureLoader(loader, Directory.DEFAULT); 1249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return loader; 1259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onLoadFinished"); 1309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsAdapter.changeCursor(0, data); 1319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa updateFilterHeaderView(); 13290f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mHandler.removeMessages(MESSAGE_SHOW_LOADING_EFFECT); 13390f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mLoadingView.setVisibility(View.VISIBLE); 1349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onLoaderReset(Loader<Cursor> loader) { 1389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onLoaderReset. "); 1399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1409b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1419b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1424e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus private class ContactTileAdapterListener implements ContactTileView.Listener { 1439b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1447a700cf798a19a8452b8671f643a05336f63f611Katherine Kuan public void onContactSelected(Uri contactUri, Rect targetRect) { 1459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (mListener != null) { 1469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mListener.onContactSelected(contactUri); 1479b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1489b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1494e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus 1504e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus @Override 1514e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus public void onCallNumberDirectly(String phoneNumber) { 1524e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus if (mListener != null) { 1534e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus mListener.onCallNumberDirectly(phoneNumber); 1544e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus } 1554e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus } 1562f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann 1572f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann @Override 1582f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann public int getApproximateTileWidth() { 1592f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann return getView().getWidth() / mContactTileAdapter.getColumnCount(); 1602f77c85543e6c497e63cd0e216b70e58c1d13ec3Daniel Lehmann } 1619b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1629b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private class FilterHeaderClickListener implements OnClickListener { 1649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1659b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onClick(View view) { 16634b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa AccountFilterUtil.startAccountFilterActivityForResult( 167b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus PhoneFavoriteFragment.this, 168b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus REQUEST_CODE_ACCOUNT_FILTER, 169b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus mFilter); 1709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private class ContactsPreferenceChangeListener 1749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa implements ContactsPreferences.ChangeListener { 1759b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 1769b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onChange() { 1779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (loadContactsPreferences()) { 1789b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa requestReloadAllContacts(); 1799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 1829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 1831dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa private class ScrollListener implements ListView.OnScrollListener { 1841dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa private boolean mShouldShowFastScroller; 1851dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa @Override 1861dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa public void onScroll(AbsListView view, 1871dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa int firstVisibleItem, int visibleItemCount, int totalItemCount) { 1881dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa // FastScroller should be visible only when the user is seeing "all" contacts section. 1891dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa final boolean shouldShow = mAdapter.shouldShowFirstScroller(firstVisibleItem); 1901dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa if (shouldShow != mShouldShowFastScroller) { 191532db253b803d98bfbbc457c5b559834cdb3b326Daisuke Miyakawa mListView.setVerticalScrollBarEnabled(shouldShow); 1921dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mListView.setFastScrollEnabled(shouldShow); 1931dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mListView.setFastScrollAlwaysVisible(shouldShow); 1941dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mShouldShowFastScroller = shouldShow; 1951dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa } 1961dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa } 1971dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa 1981dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa @Override 1991dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa public void onScrollStateChanged(AbsListView view, int scrollState) { 2001dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa } 2011dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa } 2021dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa 20390f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa private static final int MESSAGE_SHOW_LOADING_EFFECT = 1; 20490f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa private static final int LOADING_EFFECT_DELAY = 500; // ms 20590f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa private final Handler mHandler = new Handler() { 20690f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa @Override 20790f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa public void handleMessage(Message msg) { 20890f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa switch (msg.what) { 20990f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa case MESSAGE_SHOW_LOADING_EFFECT: 21090f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mLoadingView.setVisibility(View.VISIBLE); 21190f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa break; 21290f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa } 21390f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa } 21490f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa }; 21590f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa 2169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private Listener mListener; 2179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private PhoneFavoriteMergedAdapter mAdapter; 2189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private ContactTileAdapter mContactTileAdapter; 2199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private PhoneNumberListAdapter mAllContactsAdapter; 2209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 2219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa /** 2229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * true when the loader for {@link PhoneNumberListAdapter} has started already. 2239b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 2249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private boolean mAllContactsLoaderStarted; 2259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa /** 2269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * true when the loader for {@link PhoneNumberListAdapter} must reload "all" contacts again. 2279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * It typically happens when {@link ContactsPreferences} has changed its settings 2289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * (display order and sort order) 2299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 2309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private boolean mAllContactsForceReload; 2319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 2329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private ContactsPreferences mContactsPrefs; 2339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private ContactListFilter mFilter; 2349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 2359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private TextView mEmptyView; 2369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private ListView mListView; 23734b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa /** 23834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa * Layout containing {@link #mAccountFilterHeader}. Used to limit area being "pressed". 23934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa */ 24034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa private FrameLayout mAccountFilterHeaderContainer; 24134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa private View mAccountFilterHeader; 2429b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 24390f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa /** 24490f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa * Layout used when contacts load is slower than expected and thus "loading" view should be 24590f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa * shown. 24690f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa */ 24790f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa private View mLoadingView; 24890f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa 2494e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus private final ContactTileView.Listener mContactTileAdapterListener = 2509b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa new ContactTileAdapterListener(); 2519b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener = 2529b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa new ContactTileLoaderListener(); 2539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private final LoaderManager.LoaderCallbacks<Cursor> mAllContactsLoaderListener = 2549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa new AllContactsLoaderListener(); 2559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private final OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener(); 2569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private final ContactsPreferenceChangeListener mContactsPreferenceChangeListener = 2579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa new ContactsPreferenceChangeListener(); 2581dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa private final ScrollListener mScrollListener = new ScrollListener(); 2599b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 2609b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 2610da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa public void onAttach(Activity activity) { 2620da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa if (DEBUG) Log.d(TAG, "onAttach()"); 2630da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa super.onAttach(activity); 2640da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2650da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mContactsPrefs = new ContactsPreferences(activity); 2660da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2670da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. 2680da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // We don't construct the resultant adapter at this moment since it requires LayoutInflater 2690da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // that will be available on onCreateView(). 2700da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2710da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mContactTileAdapter = new ContactTileAdapter(activity, mContactTileAdapterListener, 2720da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa getResources().getInteger(R.integer.contact_tile_column_count), 2730da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa ContactTileAdapter.DisplayType.STREQUENT_PHONE_ONLY); 2740da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); 2750da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2760da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Setup the "all" adapter manually. See also the setup logic in ContactEntryListFragment. 2770da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter = new PhoneNumberListAdapter(activity); 2780da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setDisplayPhotos(true); 2790da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setQuickContactEnabled(true); 2800da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setSearchMode(false); 2810da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setIncludeProfile(false); 2820da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setSelectionVisible(false); 2830da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setDarkTheme(true); 2840da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); 2850da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Disable directory header. 2860da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setHasHeader(0, false); 2870da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Show A-Z section index. 2880da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setSectionHeaderDisplayEnabled(true); 2890da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Disable pinned header. It doesn't work with this fragment. 2900da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setPinnedPartitionHeadersEnabled(false); 2910da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Put photos on left for consistency with "frequent" contacts section. 2920da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setPhotoPosition(ContactListItemView.PhotoPosition.LEFT); 2930da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2940da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Use Callable.CONTENT_URI which will include not only phone numbers but also SIP 2950da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // addresses. 2960da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setUseCallableUri(true); 2970da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 2980da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setContactNameDisplayOrder(mContactsPrefs.getDisplayOrder()); 2990da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setSortOrder(mContactsPrefs.getSortOrder()); 3000da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa } 3010da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 3020da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa @Override 3039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onCreate(Bundle savedState) { 3040da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa if (DEBUG) Log.d(TAG, "onCreate()"); 3059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa super.onCreate(savedState); 3069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (savedState != null) { 3079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mFilter = savedState.getParcelable(KEY_FILTER); 3080da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 3090da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa if (mFilter != null) { 3100da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setFilter(mFilter); 3110da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa } 3129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 3137c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa setHasOptionsMenu(true); 3149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 3159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 3179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onSaveInstanceState(Bundle outState) { 3189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa super.onSaveInstanceState(outState); 3199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa outState.putParcelable(KEY_FILTER, mFilter); 3209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 3219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 3235db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa public View onCreateView(LayoutInflater inflater, ViewGroup container, 3245db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa Bundle savedInstanceState) { 325902170690532fceb9a3e13ad00f6aff00f95b10fDaisuke Miyakawa final View listLayout = inflater.inflate( 326902170690532fceb9a3e13ad00f6aff00f95b10fDaisuke Miyakawa R.layout.phone_contact_tile_list, container, false); 3275db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa 3285db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list); 3295db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setItemsCanFocus(true); 3305db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setOnItemClickListener(this); 331532db253b803d98bfbbc457c5b559834cdb3b326Daisuke Miyakawa mListView.setVerticalScrollBarEnabled(false); 3325db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); 3335db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); 3349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3350da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Create the account filter header but keep it hidden until "all" contacts are loaded. 3360da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAccountFilterHeaderContainer = new FrameLayout(getActivity(), null); 3370da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAccountFilterHeader = inflater.inflate(R.layout.account_filter_header_for_phone_favorite, 3380da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mListView, false); 3390da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener); 3400da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAccountFilterHeaderContainer.addView(mAccountFilterHeader); 34190f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa 34290f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mLoadingView = inflater.inflate(R.layout.phone_loading_contacts, mListView, false); 3430da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa 3440da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAdapter = new PhoneFavoriteMergedAdapter(getActivity(), 34590f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mContactTileAdapter, mAccountFilterHeaderContainer, mAllContactsAdapter, 34690f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mLoadingView); 3475db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa 3485db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setAdapter(mAdapter); 3495db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa 3501dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mListView.setOnScrollListener(mScrollListener); 3511dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mListView.setFastScrollEnabled(false); 3521dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa mListView.setFastScrollAlwaysVisible(false); 3531dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa 3545db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty); 3555db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mEmptyView.setText(getString(R.string.listTotalAllContactsZero)); 3565db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mListView.setEmptyView(mEmptyView); 3579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa updateFilterHeaderView(); 3595db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa 3605db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa return listLayout; 3619b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 3629b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 3647c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 3657c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa super.onCreateOptionsMenu(menu, inflater); 366091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawa inflater.inflate(R.menu.phone_favorite_options, menu); 3677c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa } 3687c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa 3697c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa @Override 3707c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa public boolean onOptionsItemSelected(MenuItem item) { 3717c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa switch (item.getItemId()) { 3727c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa case R.id.menu_import_export: 373e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus // We hard-code the "contactsAreAvailable" argument because doing it properly would 374e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus // involve querying a {@link ProviderStatusLoader}, which we don't want to do right 375091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawa // now in Dialtacts for (potential) performance reasons. Compare with how it is 376e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus // done in {@link PeopleActivity}. 377e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus ImportExportDialogFragment.show(getFragmentManager(), true); 3787c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa return true; 3797c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa case R.id.menu_accounts: 3807c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS); 3817c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] { 3827c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa ContactsContract.AUTHORITY 3837c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa }); 3847c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 3857c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa startActivity(intent); 3867c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa return true; 3877c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa } 3887c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa return false; 3897c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa } 3907c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa 3917c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa @Override 3929b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onStart() { 3939b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa super.onStart(); 3949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3959b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mContactsPrefs.registerChangeListener(mContactsPreferenceChangeListener); 3969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 3979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // If ContactsPreferences has changed, we need to reload "all" contacts with the new 3989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // settings. If mAllContactsFoarceReload is already true, it should be kept. 3999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (loadContactsPreferences()) { 4009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsForceReload = true; 4019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4030da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa // Use initLoader() instead of restartLoader() to refraining unnecessary reload. 4049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will 4059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // be called, on which we'll check if "all" contacts should be reloaded again or not. 4069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); 40790f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa 40890f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa // Delay showing "loading" view until certain amount of time so that users won't see 40990f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa // instant flash of the view when the contacts load is fast enough. 41090f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa // This will be kept shown until both tile and all sections are loaded. 41190f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mLoadingView.setVisibility(View.INVISIBLE); 41290f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa mHandler.sendEmptyMessageDelayed(MESSAGE_SHOW_LOADING_EFFECT, LOADING_EFFECT_DELAY); 4139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 4169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onStop() { 4179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa super.onStop(); 4189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mContactsPrefs.unregisterChangeListener(); 4199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa /** 4229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * {@inheritDoc} 4239b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * 4249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * This is only effective for elements provided by {@link #mContactTileAdapter}. 4259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * {@link #mContactTileAdapter} has its own logic for click events. 4269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 4279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa @Override 4289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 4299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa final int contactTileAdapterCount = mContactTileAdapter.getCount(); 4309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (position <= contactTileAdapterCount) { 4319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa Log.e(TAG, "onItemClick() event for unexpected position. " 4329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa + "The position " + position + " is before \"all\" section. Ignored."); 4339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } else { 4349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa final int localPosition = position - mContactTileAdapter.getCount() - 1; 4359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (mListener != null) { 4369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mListener.onContactSelected(mAllContactsAdapter.getDataUri(localPosition)); 4379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4409b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 44134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa @Override 44234b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa public void onActivityResult(int requestCode, int resultCode, Intent data) { 44334b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) { 44434b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa if (getActivity() != null) { 44534b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa AccountFilterUtil.handleAccountFilterResult( 44634b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa ContactListFilterController.getInstance(getActivity()), resultCode, data); 44734b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa } else { 44834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()"); 44934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa } 45034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa } 45134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa } 45234b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa 4539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private boolean loadContactsPreferences() { 4549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (mContactsPrefs == null || mAllContactsAdapter == null) { 4559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return false; 4569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa boolean changed = false; 4590da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa final int currentDisplayOrder = mContactsPrefs.getDisplayOrder(); 4600da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa if (mAllContactsAdapter.getContactNameDisplayOrder() != currentDisplayOrder) { 4610da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setContactNameDisplayOrder(currentDisplayOrder); 4629b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa changed = true; 4639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4650da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa final int currentSortOrder = mContactsPrefs.getSortOrder(); 4660da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa if (mAllContactsAdapter.getSortOrder() != currentSortOrder) { 4670da88d6359b1b8c7f4998d7f58a467ad65d40f84Daisuke Miyakawa mAllContactsAdapter.setSortOrder(currentSortOrder); 4689b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa changed = true; 4699b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return changed; 4729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa /** 4759b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Requests to reload "all" contacts. If the section is already loaded, this method will 4769b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * force reloading it now. If the section isn't loaded yet, the actual load may be done later 4779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * (on {@link #onStart()}. 4789b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */ 4799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private void requestReloadAllContacts() { 4809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) { 4819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa Log.d(TAG, "requestReloadAllContacts()" 4829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa + " mAllContactsAdapter: " + mAllContactsAdapter 4839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa + ", mAllContactsLoaderStarted: " + mAllContactsLoaderStarted); 4849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (mAllContactsAdapter == null || !mAllContactsLoaderStarted) { 4879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // Remember this request until next load on onStart(). 4889b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsForceReload = true; 4899b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return; 4909b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4919b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4929b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) Log.d(TAG, "Reload \"all\" contacts now."); 4939b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mAllContactsAdapter.onDataReload(); 4959b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa // Use restartLoader() to make LoaderManager to load the section again. 4969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa getLoaderManager().restartLoader(LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener); 4979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 4989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 4999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa private void updateFilterHeaderView() { 5009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa final ContactListFilter filter = getFilter(); 50134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa if (mAccountFilterHeader == null || mAllContactsAdapter == null || filter == null) { 50234b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa return; 5039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 50490f40d0162e4cee5b94bf3203c059e27f6472fabDaisuke Miyakawa AccountFilterUtil.updateAccountFilterTitleForPhone(mAccountFilterHeader, filter, true); 5059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 5069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public ContactListFilter getFilter() { 5089b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return mFilter; 5099b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 5109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void setFilter(ContactListFilter filter) { 5129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if ((mFilter == null && filter == null) || (mFilter != null && mFilter.equals(filter))) { 5139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa return; 5149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 5159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa if (DEBUG) { 5179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa Log.d(TAG, "setFilter(). old filter (" + mFilter 5189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa + ") will be replaced with new filter (" + filter + ")"); 5199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 5209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mFilter = filter; 5229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5235db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa if (mAllContactsAdapter != null) { 5245db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa mAllContactsAdapter.setFilter(mFilter); 5255db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa requestReloadAllContacts(); 5265db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa updateFilterHeaderView(); 5275db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa } 5289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 5299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa 5309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa public void setListener(Listener listener) { 5319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa mListener = listener; 5329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa } 533aabc1e81c2d43827fe2ad0bdde6851bdfb431924Josh Gargus} 534