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