ContactBrowseListFragment.java revision 8c6955ff3c05e1f3899110701c3cb5559a492f1e
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.contacts.list;
17
18import com.android.contacts.R;
19import com.android.contacts.widget.ListViewUtils;
20
21import android.app.LoaderManager.LoaderCallbacks;
22import android.content.CursorLoader;
23import android.content.Loader;
24import android.database.Cursor;
25import android.net.Uri;
26import android.os.Bundle;
27import android.provider.ContactsContract;
28import android.provider.ContactsContract.Contacts;
29import android.provider.ContactsContract.Directory;
30import android.text.TextUtils;
31import android.widget.ListView;
32
33/**
34 * Fragment containing a contact list used for browsing (as compared to
35 * picking a contact with one of the PICK intents).
36 */
37public abstract class ContactBrowseListFragment extends
38        ContactEntryListFragment<ContactListAdapter> {
39
40    private static final String KEY_SELECTED_URI = "selectedUri";
41
42    private static final int SELECTED_ID_LOADER = -3;
43
44    private Uri mSelectedContactUri;
45    private long mSelectedContactDirectoryId;
46    private String mSelectedContactLookupKey;
47    private boolean mScrollToSelectionRequested;
48
49    private OnContactBrowserActionListener mListener;
50
51    private LoaderCallbacks<Cursor> mIdLoaderCallbacks = new LoaderCallbacks<Cursor>() {
52
53        @Override
54        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
55            return new CursorLoader(getContext(),
56                    mSelectedContactUri,
57                    new String[] { Contacts.LOOKUP_KEY },
58                    null,
59                    null,
60                    null);
61        }
62
63        @Override
64        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
65            String lookupKey = null;
66            if (data != null) {
67                if (data.moveToFirst()) {
68                    lookupKey = data.getString(0);
69                }
70            }
71            if (!TextUtils.equals(mSelectedContactLookupKey, lookupKey)) {
72                mSelectedContactLookupKey = lookupKey;
73                configureContactSelection();
74            }
75            return;
76        }
77    };
78
79    @Override
80    public void restoreSavedState(Bundle savedState) {
81        super.restoreSavedState(savedState);
82
83        if (savedState == null) {
84            return;
85        }
86
87        mSelectedContactUri = savedState.getParcelable(KEY_SELECTED_URI);
88        parseSelectedContactUri();
89    }
90
91    @Override
92    public void onSaveInstanceState(Bundle outState) {
93        super.onSaveInstanceState(outState);
94        outState.putParcelable(KEY_SELECTED_URI, mSelectedContactUri);
95    }
96
97    @Override
98    public void onStart() {
99        // Refresh the currently selected lookup in case it changed while we were sleeping
100        startLoadingContactLookupKey();
101        super.onStart();
102   }
103
104    protected void startLoadingContactLookupKey() {
105        if (isSelectionVisible() && mSelectedContactUri != null &&
106                (mSelectedContactDirectoryId == Directory.DEFAULT ||
107                        mSelectedContactDirectoryId == Directory.LOCAL_INVISIBLE)) {
108            getLoaderManager().restartLoader(SELECTED_ID_LOADER, null, mIdLoaderCallbacks);
109        } else {
110            getLoaderManager().stopLoader(SELECTED_ID_LOADER);
111        }
112    }
113
114    @Override
115    protected void prepareEmptyView() {
116        if (isSearchMode()) {
117            return;
118        } else if (isSyncActive()) {
119            if (hasIccCard()) {
120                setEmptyText(R.string.noContactsHelpTextWithSync);
121            } else {
122                setEmptyText(R.string.noContactsNoSimHelpTextWithSync);
123            }
124        } else {
125            if (hasIccCard()) {
126                setEmptyText(R.string.noContactsHelpText);
127            } else {
128                setEmptyText(R.string.noContactsNoSimHelpText);
129            }
130        }
131    }
132
133    public Uri getSelectedContactUri() {
134        return mSelectedContactUri;
135    }
136
137    public void setSelectedContactUri(Uri uri) {
138        if (mSelectedContactUri == null
139                || (mSelectedContactUri != null && !mSelectedContactUri.equals(uri))) {
140            mSelectedContactUri = uri;
141
142            parseSelectedContactUri();
143
144            if (isAdded()) {
145                // Configure the adapter to show the selection based on the lookup key extracted
146                // from the URI
147                configureAdapter();
148
149                // Also, launch a loader to pick up a new lookup key in case it has changed
150                startLoadingContactLookupKey();
151            }
152        }
153    }
154
155    private void parseSelectedContactUri() {
156        if (mSelectedContactUri != null) {
157            if (!mSelectedContactUri.toString()
158                    .startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
159                throw new IllegalStateException(
160                        "Contact list contains a non-lookup URI: " + mSelectedContactUri);
161            }
162
163            String directoryParam =
164                mSelectedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
165            mSelectedContactDirectoryId = TextUtils.isEmpty(directoryParam)
166                    ? Directory.DEFAULT
167                    : Long.parseLong(directoryParam);
168            mSelectedContactLookupKey =
169                    Uri.encode(mSelectedContactUri.getPathSegments().get(2));
170        } else {
171            mSelectedContactDirectoryId = Directory.DEFAULT;
172            mSelectedContactLookupKey = null;
173        }
174    }
175
176    @Override
177    protected void configureAdapter() {
178        super.configureAdapter();
179        configureContactSelection();
180    }
181
182    /**
183     * Configures the adapter with the identity of the currently selected contact.
184     */
185    private void configureContactSelection() {
186        ContactListAdapter adapter = getAdapter();
187        if (adapter == null) {
188            return;
189        }
190
191        adapter.setSelectedContact(mSelectedContactDirectoryId, mSelectedContactLookupKey);
192    }
193
194    public void setOnContactListActionListener(OnContactBrowserActionListener listener) {
195        mListener = listener;
196    }
197
198    public void createNewContact() {
199        mListener.onCreateNewContactAction();
200    }
201
202    public void viewContact(Uri contactUri, boolean finishEditing) {
203        mListener.onViewContactAction(contactUri, finishEditing);
204    }
205
206    public void editContact(Uri contactUri) {
207        mListener.onEditContactAction(contactUri);
208    }
209
210    public void deleteContact(Uri contactUri) {
211        mListener.onDeleteContactAction(contactUri);
212    }
213
214    public void addToFavorites(Uri contactUri) {
215        mListener.onAddToFavoritesAction(contactUri);
216    }
217
218    public void removeFromFavorites(Uri contactUri) {
219        mListener.onRemoveFromFavoritesAction(contactUri);
220    }
221
222    public void callContact(Uri contactUri) {
223        mListener.onCallContactAction(contactUri);
224    }
225
226    public void smsContact(Uri contactUri) {
227        mListener.onSmsContactAction(contactUri);
228    }
229
230    @Override
231    protected void finish() {
232        super.finish();
233        mListener.onFinishAction();
234    }
235
236    public void scrollToSelectedContact() {
237        mScrollToSelectionRequested = true;
238        scrollToSelectedContactIfNeeded();
239    }
240
241    @Override
242    protected void completeRestoreInstanceState() {
243        super.completeRestoreInstanceState();
244        scrollToSelectedContactIfNeeded();
245    }
246
247    private void scrollToSelectedContactIfNeeded() {
248        if (!mScrollToSelectionRequested) {
249            return;
250        }
251
252        ContactListAdapter adapter = getAdapter();
253        if (adapter == null) {
254            return;
255        }
256
257        int position = adapter.getSelectedContactPosition();
258        if (position != -1) {
259            mScrollToSelectionRequested = false;
260            ListView listView = getListView();
261            ListViewUtils.smartSmoothScrollToPosition(
262                    listView, position + listView.getHeaderViewsCount());
263        }
264    }
265}
266