PhoneFavoriteFragment.java revision aabc1e81c2d43827fe2ad0bdde6851bdfb431924
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.Context;
299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.CursorLoader;
309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.Intent;
319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.content.Loader;
329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.database.Cursor;
337a700cf798a19a8452b8671f643a05336f63f611Katherine Kuanimport android.graphics.Rect;
349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.net.Uri;
359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.os.Bundle;
367c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.provider.ContactsContract;
379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.provider.ContactsContract.Directory;
387c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.provider.Settings;
399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.util.Log;
409b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.LayoutInflater;
417c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.Menu;
427c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.MenuInflater;
437c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawaimport android.view.MenuItem;
449b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.View;
459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.View.OnClickListener;
469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.view.ViewGroup;
471dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawaimport android.widget.AbsListView;
489b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.AdapterView;
499b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener;
5034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawaimport android.widget.FrameLayout;
519b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.ListView;
529b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawaimport android.widget.TextView;
539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa/**
559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * Fragment for Phone UI's favorite screen.
569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa *
579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * This fragment contains three kinds of contacts in one screen: "starred", "frequent", and "all"
589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * contacts. To show them at once, this merges results from {@link ContactTileAdapter} and
599b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * {@link PhoneNumberListAdapter} into one unified list using {@link PhoneFavoriteMergedAdapter}.
609b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa * A contact filter header is also inserted between those adapters' results.
619b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa */
62091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawapublic class PhoneFavoriteFragment extends Fragment implements OnItemClickListener {
639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private static final String TAG = PhoneFavoriteFragment.class.getSimpleName();
649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private static final boolean DEBUG = false;
659b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
669b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * Used with LoaderManager.
689b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
699b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private static int LOADER_ID_CONTACT_TILE = 1;
709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private static int LOADER_ID_ALL_CONTACTS = 2;
719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private static final String KEY_FILTER = "filter";
739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
7434b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
7534b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa
769b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public interface Listener {
779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onContactSelected(Uri contactUri);
784e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus        public void onCallNumberDirectly(String phoneNumber);
799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public CursorLoader onCreateLoader(int id, Bundle args) {
849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader.");
859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity());
869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
889b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
899b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
909b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished");
919b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mContactTileAdapter.setContactCursor(data);
929b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
939b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (mAllContactsForceReload) {
949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                mAllContactsAdapter.onDataReload();
959b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                // Use restartLoader() to make LoaderManager to load the section again.
969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                getLoaderManager().restartLoader(
979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                        LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener);
989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            } else if (!mAllContactsLoaderStarted) {
999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                // Load "all" contacts if not loaded yet.
1009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                getLoaderManager().initLoader(
1019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                        LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener);
1029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            }
1039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsForceReload = false;
1049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsLoaderStarted = true;
1059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            // Show the filter header with "loading" state.
1079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            updateFilterHeaderView();
10834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            mAccountFilterHeader.setVisibility(View.VISIBLE);
1099b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onLoaderReset(Loader<Cursor> loader) {
1139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. ");
1149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
1169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private class AllContactsLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
1189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1199b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
1209b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onCreateLoader");
1219b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            CursorLoader loader = new CursorLoader(getActivity(), null, null, null, null, null);
1229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsAdapter.configureLoader(loader, Directory.DEFAULT);
1239b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            return loader;
1249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
1289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onLoadFinished");
1299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsAdapter.changeCursor(0, data);
1309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            updateFilterHeaderView();
1319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
1329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onLoaderReset(Loader<Cursor> loader) {
1369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onLoaderReset. ");
1379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
1399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1404e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus    private class ContactTileAdapterListener implements ContactTileView.Listener {
1419b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1427a700cf798a19a8452b8671f643a05336f63f611Katherine Kuan        public void onContactSelected(Uri contactUri, Rect targetRect) {
1439b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (mListener != null) {
1449b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                mListener.onContactSelected(contactUri);
1459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            }
1469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1474e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus
1484e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus        @Override
1494e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus        public void onCallNumberDirectly(String phoneNumber) {
1504e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus            if (mListener != null) {
1514e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus                mListener.onCallNumberDirectly(phoneNumber);
1524e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus            }
1534e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus        }
1549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
1559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private class FilterHeaderClickListener implements OnClickListener {
1579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onClick(View view) {
15934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            AccountFilterUtil.startAccountFilterActivityForResult(
160b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus                    PhoneFavoriteFragment.this,
161b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus                    REQUEST_CODE_ACCOUNT_FILTER,
162b6553457d0c3e84eefa0a853090b680090a7b2f9Josh Gargus                    mFilter);
1639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
1659b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1669b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private class ContactsPreferenceChangeListener
1679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            implements ContactsPreferences.ChangeListener {
1689b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        @Override
1699b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        public void onChange() {
1709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (loadContactsPreferences()) {
1719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                requestReloadAllContacts();
1729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            }
1739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
1749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
1759b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
1761dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa    private class ScrollListener implements ListView.OnScrollListener {
1771dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        private boolean mShouldShowFastScroller;
1781dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        @Override
1791dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        public void onScroll(AbsListView view,
1801dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa                int firstVisibleItem, int visibleItemCount, int totalItemCount) {
1811dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa            // FastScroller should be visible only when the user is seeing "all" contacts section.
1821dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa            final boolean shouldShow = mAdapter.shouldShowFirstScroller(firstVisibleItem);
1831dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa            if (shouldShow != mShouldShowFastScroller) {
184532db253b803d98bfbbc457c5b559834cdb3b326Daisuke Miyakawa                mListView.setVerticalScrollBarEnabled(shouldShow);
1851dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa                mListView.setFastScrollEnabled(shouldShow);
1861dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa                mListView.setFastScrollAlwaysVisible(shouldShow);
1871dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa                mShouldShowFastScroller = shouldShow;
1881dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa            }
1891dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        }
1901dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa
1911dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        @Override
1921dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        public void onScrollStateChanged(AbsListView view, int scrollState) {
1931dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        }
1941dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa    }
1951dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa
1969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private Listener mListener;
1979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private PhoneFavoriteMergedAdapter mAdapter;
1989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private ContactTileAdapter mContactTileAdapter;
1999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private PhoneNumberListAdapter mAllContactsAdapter;
2009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
2029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * true when the loader for {@link PhoneNumberListAdapter} has started already.
2039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
2049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private boolean mAllContactsLoaderStarted;
2059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
2069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * true when the loader for {@link PhoneNumberListAdapter} must reload "all" contacts again.
2079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * It typically happens when {@link ContactsPreferences} has changed its settings
2089b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * (display order and sort order)
2099b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
2109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private boolean mAllContactsForceReload;
2119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private ContactsPreferences mContactsPrefs;
2139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private ContactListFilter mFilter;
2149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private TextView mEmptyView;
2169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private ListView mListView;
21734b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    /**
21834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa     * Layout containing {@link #mAccountFilterHeader}. Used to limit area being "pressed".
21934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa     */
22034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    private FrameLayout mAccountFilterHeaderContainer;
22134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    private View mAccountFilterHeader;
2229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2234e05a29c9b05c8cb74972aa5b9fe55fe35d7f45dJosh Gargus    private final ContactTileView.Listener mContactTileAdapterListener =
2249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            new ContactTileAdapterListener();
2259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener =
2269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            new ContactTileLoaderListener();
2279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private final LoaderManager.LoaderCallbacks<Cursor> mAllContactsLoaderListener =
2289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            new AllContactsLoaderListener();
2299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private final OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
2309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private final ContactsPreferenceChangeListener mContactsPreferenceChangeListener =
2319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            new ContactsPreferenceChangeListener();
2321dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa    private final ScrollListener mScrollListener = new ScrollListener();
2339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
2359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onCreate(Bundle savedState) {
2369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        super.onCreate(savedState);
2379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (savedState != null) {
2389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mFilter = savedState.getParcelable(KEY_FILTER);
2399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
2407c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa        setHasOptionsMenu(true);
2419b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
2429b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2439b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
2449b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onSaveInstanceState(Bundle outState) {
2459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        super.onSaveInstanceState(outState);
2469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        outState.putParcelable(KEY_FILTER, mFilter);
2479b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
2489b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2499b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
2509b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onAttach(Activity activity) {
2519b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        super.onAttach(activity);
2529b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mContactsPrefs = new ContactsPreferences(activity);
2545db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa    }
2559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2565db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa    @Override
2575db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa    public View onCreateView(LayoutInflater inflater, ViewGroup container,
2585db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa            Bundle savedInstanceState) {
2595db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        final View listLayout = inflater.inflate(R.layout.contact_tile_list, container, false);
2605db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
2615db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list);
2625db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setItemsCanFocus(true);
2635db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setOnItemClickListener(this);
264532db253b803d98bfbbc457c5b559834cdb3b326Daisuke Miyakawa        mListView.setVerticalScrollBarEnabled(false);
2655db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT);
2665db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
2679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2685db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        initAdapters(getActivity(), inflater);
2695db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
2705db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setAdapter(mAdapter);
2715db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
2721dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        mListView.setOnScrollListener(mScrollListener);
2731dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        mListView.setFastScrollEnabled(false);
2741dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa        mListView.setFastScrollAlwaysVisible(false);
2751dff6b60c28fa34e477b84c95c4bbe6c9b482416Daisuke Miyakawa
2765db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty);
2775db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mEmptyView.setText(getString(R.string.listTotalAllContactsZero));
2785db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mListView.setEmptyView(mEmptyView);
2799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        updateFilterHeaderView();
2815db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
2825db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        return listLayout;
2839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
2849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
2859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
2869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * Constructs and initializes {@link #mContactTileAdapter}, {@link #mAllContactsAdapter}, and
2879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * {@link #mAllContactsAdapter}.
2885db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     *
2895db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     * TODO: Move all the code here to {@link PhoneFavoriteMergedAdapter} if possible.
2905db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     * There are two problems: account header (whose content changes depending on filter settings)
2915db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     * and OnClickListener (which initiates {@link Activity#startActivityForResult(Intent, int)}).
2925db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     * See also issue 5429203, 5269692, and 5432286. If we are able to have a singleton for filter,
2935db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa     * this work will become easier.
2949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
2955db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa    private void initAdapters(Context context, LayoutInflater inflater) {
2969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mContactTileAdapter = new ContactTileAdapter(context, mContactTileAdapterListener,
2979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                getResources().getInteger(R.integer.contact_tile_column_count),
2989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                ContactTileAdapter.DisplayType.STREQUENT_PHONE_ONLY);
2999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(context));
3009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Setup the "all" adapter manually. See also the setup logic in ContactEntryListFragment.
3029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter = new PhoneNumberListAdapter(context);
3039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setDisplayPhotos(true);
3049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setQuickContactEnabled(true);
3059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setSearchMode(false);
3069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setIncludeProfile(false);
3079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setSelectionVisible(false);
3089b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setDarkTheme(true);
3099b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setPhotoLoader(ContactPhotoManager.getInstance(context));
3109b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Disable directory header.
3119b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setHasHeader(0, false);
3129b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Show A-Z section index.
3139b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setSectionHeaderDisplayEnabled(true);
3149b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Disable pinned header. It doesn't work with this fragment.
3159b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setPinnedPartitionHeadersEnabled(false);
3169b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Put photos on left for consistency with "frequent" contacts section.
3179b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.setPhotoPosition(ContactListItemView.PhotoPosition.LEFT);
3189b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
319e1c007eeb40a40b21e60bb4c8a42e0affd9fcdd1Daisuke Miyakawa        mAllContactsAdapter.setUseCallableUri(true);
320e1c007eeb40a40b21e60bb4c8a42e0affd9fcdd1Daisuke Miyakawa
3215db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        if (mFilter != null) {
3225db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa            mAllContactsAdapter.setFilter(mFilter);
3235db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        }
3245db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
3255db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        // Create the account filter header but keep it hidden until "all" contacts are loaded.
32634b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        mAccountFilterHeaderContainer = new FrameLayout(context, null);
327b5c0b93e37e2b471ea46a1889e2eb194292284b7Daisuke Miyakawa        mAccountFilterHeader = inflater.inflate(R.layout.account_filter_header_for_phone_favorite,
328b5c0b93e37e2b471ea46a1889e2eb194292284b7Daisuke Miyakawa                mListView, false);
32934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
33034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        mAccountFilterHeaderContainer.addView(mAccountFilterHeader);
3315db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mAccountFilterHeaderContainer.setVisibility(View.GONE);
3325db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
3335db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        mAdapter = new PhoneFavoriteMergedAdapter(context,
3345db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa                mContactTileAdapter, mAccountFilterHeaderContainer, mAllContactsAdapter);
3355db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa
3369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
3379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
3397c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
3407c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa        super.onCreateOptionsMenu(menu, inflater);
341091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawa        inflater.inflate(R.menu.phone_favorite_options, menu);
3427c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    }
3437c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa
3447c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    @Override
3457c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    public boolean onOptionsItemSelected(MenuItem item) {
3467c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa        switch (item.getItemId()) {
3477c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa            case R.id.menu_import_export:
348e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus                // We hard-code the "contactsAreAvailable" argument because doing it properly would
349e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus                // involve querying a {@link ProviderStatusLoader}, which we don't want to do right
350091034c2d4c3ea69fc63c2e9d0956a109a13e08eDaisuke Miyakawa                // now in Dialtacts for (potential) performance reasons.  Compare with how it is
351e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus                // done in {@link PeopleActivity}.
352e05f8efc11a383b8299e3a16b79a5d27531251d4Josh Gargus                ImportExportDialogFragment.show(getFragmentManager(), true);
3537c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                return true;
3547c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa            case R.id.menu_accounts:
3557c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
3567c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {
3577c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                    ContactsContract.AUTHORITY
3587c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                });
3597c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3607c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                startActivity(intent);
3617c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa                return true;
3627c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa        }
3637c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa        return false;
3647c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    }
3657c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa
3667c30236364c71618da4b266a61a77e9711aa23f1Daisuke Miyakawa    @Override
3679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onStart() {
3689b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        super.onStart();
3699b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mContactsPrefs.registerChangeListener(mContactsPreferenceChangeListener);
3719b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3729b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // If ContactsPreferences has changed, we need to reload "all" contacts with the new
3739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // settings. If mAllContactsFoarceReload is already true, it should be kept.
3749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (loadContactsPreferences()) {
3759b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsForceReload = true;
3769b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
3779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3789b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Use initLoader() instead of reloadLoader() to refraing unnecessary reload.
3799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
3809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // be called, on which we'll check if "all" contacts should be reloaded again or not.
3819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);
3829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
3839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
3859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onStop() {
3869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        super.onStop();
3879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mContactsPrefs.unregisterChangeListener();
3889b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
3899b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
3909b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
3919b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * {@inheritDoc}
3929b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     *
3939b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * This is only effective for elements provided by {@link #mContactTileAdapter}.
3949b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * {@link #mContactTileAdapter} has its own logic for click events.
3959b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
3969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    @Override
3979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
3989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        final int contactTileAdapterCount = mContactTileAdapter.getCount();
3999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (position <= contactTileAdapterCount) {
4009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            Log.e(TAG, "onItemClick() event for unexpected position. "
4019b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                    + "The position " + position + " is before \"all\" section. Ignored.");
4029b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        } else {
4039b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            final int localPosition = position - mContactTileAdapter.getCount() - 1;
4049b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            if (mListener != null) {
4059b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                mListener.onContactSelected(mAllContactsAdapter.getDataUri(localPosition));
4069b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            }
4079b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4089b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4099b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
41034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    @Override
41134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    public void onActivityResult(int requestCode, int resultCode, Intent data) {
41234b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
41334b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            if (getActivity() != null) {
41434b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa                AccountFilterUtil.handleAccountFilterResult(
41534b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa                        ContactListFilterController.getInstance(getActivity()), resultCode, data);
41634b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            } else {
41734b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa                Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
41834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            }
41934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        }
42034b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa    }
42134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa
4229b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private boolean loadContactsPreferences() {
4239b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (mContactsPrefs == null || mAllContactsAdapter == null) {
4249b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            return false;
4259b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4269b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4279b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        boolean changed = false;
4289b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (mAllContactsAdapter.getContactNameDisplayOrder() != mContactsPrefs.getDisplayOrder()) {
4299b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsAdapter.setContactNameDisplayOrder(mContactsPrefs.getDisplayOrder());
4309b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            changed = true;
4319b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4329b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4339b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (mAllContactsAdapter.getSortOrder() != mContactsPrefs.getSortOrder()) {
4349b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsAdapter.setSortOrder(mContactsPrefs.getSortOrder());
4359b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            changed = true;
4369b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4379b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4389b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        return changed;
4399b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4409b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4419b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    /**
4429b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * Requests to reload "all" contacts. If the section is already loaded, this method will
4439b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * force reloading it now. If the section isn't loaded yet, the actual load may be done later
4449b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     * (on {@link #onStart()}.
4459b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa     */
4469b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private void requestReloadAllContacts() {
4479b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (DEBUG) {
4489b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            Log.d(TAG, "requestReloadAllContacts()"
4499b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                    + " mAllContactsAdapter: " + mAllContactsAdapter
4509b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                    + ", mAllContactsLoaderStarted: " + mAllContactsLoaderStarted);
4519b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4529b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4539b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (mAllContactsAdapter == null || !mAllContactsLoaderStarted) {
4549b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            // Remember this request until next load on onStart().
4559b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            mAllContactsForceReload = true;
4569b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            return;
4579b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4589b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4599b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (DEBUG) Log.d(TAG, "Reload \"all\" contacts now.");
4609b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4619b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mAllContactsAdapter.onDataReload();
4629b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        // Use restartLoader() to make LoaderManager to load the section again.
4639b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        getLoaderManager().restartLoader(LOADER_ID_ALL_CONTACTS, null, mAllContactsLoaderListener);
4649b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4659b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4669b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    private void updateFilterHeaderView() {
4679b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        final ContactListFilter filter = getFilter();
46834b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        if (mAccountFilterHeader == null || mAllContactsAdapter == null || filter == null) {
46934b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa            return;
4709b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
47134b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa        AccountFilterUtil.updateAccountFilterTitleForPhone(
47234b901ca7781cf7fdd4f6275ef98ae73c95749c2Daisuke Miyakawa                mAccountFilterHeader, filter, mAllContactsAdapter.isLoading(), true);
4739b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4749b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4759b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public ContactListFilter getFilter() {
4769b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        return mFilter;
4779b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4789b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4799b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void setFilter(ContactListFilter filter) {
4809b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if ((mFilter == null && filter == null) || (mFilter != null && mFilter.equals(filter))) {
4819b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            return;
4829b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4839b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4849b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        if (DEBUG) {
4859b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa            Log.d(TAG, "setFilter(). old filter (" + mFilter
4869b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa                    + ") will be replaced with new filter (" + filter + ")");
4879b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        }
4889b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4899b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mFilter = filter;
4909b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4915db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        if (mAllContactsAdapter != null) {
4925db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa            mAllContactsAdapter.setFilter(mFilter);
4935db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa            requestReloadAllContacts();
4945db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa            updateFilterHeaderView();
4955db4f136163675105813900b1f3f7da48bde97b6Daisuke Miyakawa        }
4969b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
4979b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa
4989b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    public void setListener(Listener listener) {
4999b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa        mListener = listener;
5009b9104874ec0680ac60cb0527d127fc1c34bdb7eDaisuke Miyakawa    }
501aabc1e81c2d43827fe2ad0bdde6851bdfb431924Josh Gargus}
502