ContactBrowseListFragment.java revision e20d3432a370dd3996deec2df4e3cdf726c94992
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 static final int SELECTION_VISIBILITY_REQUEST_NONE = 0; 45 private static final int SELECTION_VISIBILITY_REQUEST_SMOOTH = 1; 46 private static final int SELECTION_VISIBILITY_REQUEST_INSTANT = 2; 47 48 private Uri mSelectedContactUri; 49 private long mSelectedContactDirectoryId; 50 private String mSelectedContactLookupKey; 51 private int mSelectionVisibilityRequest; 52 53 private OnContactBrowserActionListener mListener; 54 55 private LoaderCallbacks<Cursor> mIdLoaderCallbacks = new LoaderCallbacks<Cursor>() { 56 57 @Override 58 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 59 return new CursorLoader(getContext(), 60 mSelectedContactUri, 61 new String[] { Contacts.LOOKUP_KEY }, 62 null, 63 null, 64 null); 65 } 66 67 @Override 68 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 69 String lookupKey = null; 70 if (data != null) { 71 if (data.moveToFirst()) { 72 lookupKey = data.getString(0); 73 } 74 } 75 if (!TextUtils.equals(mSelectedContactLookupKey, lookupKey)) { 76 mSelectedContactLookupKey = lookupKey; 77 configureContactSelection(); 78 } 79 return; 80 } 81 }; 82 83 @Override 84 public void restoreSavedState(Bundle savedState) { 85 super.restoreSavedState(savedState); 86 87 if (savedState == null) { 88 return; 89 } 90 91 mSelectedContactUri = savedState.getParcelable(KEY_SELECTED_URI); 92 parseSelectedContactUri(); 93 } 94 95 @Override 96 public void onSaveInstanceState(Bundle outState) { 97 super.onSaveInstanceState(outState); 98 outState.putParcelable(KEY_SELECTED_URI, mSelectedContactUri); 99 } 100 101 @Override 102 public void onStart() { 103 // Refresh the currently selected lookup in case it changed while we were sleeping 104 startLoadingContactLookupKey(); 105 super.onStart(); 106 } 107 108 protected void startLoadingContactLookupKey() { 109 if (isSelectionVisible() && mSelectedContactUri != null && 110 (mSelectedContactDirectoryId == Directory.DEFAULT || 111 mSelectedContactDirectoryId == Directory.LOCAL_INVISIBLE)) { 112 getLoaderManager().restartLoader(SELECTED_ID_LOADER, null, mIdLoaderCallbacks); 113 } else { 114 getLoaderManager().stopLoader(SELECTED_ID_LOADER); 115 } 116 } 117 118 @Override 119 protected void prepareEmptyView() { 120 if (isSearchMode()) { 121 return; 122 } else if (isSyncActive()) { 123 if (hasIccCard()) { 124 setEmptyText(R.string.noContactsHelpTextWithSync); 125 } else { 126 setEmptyText(R.string.noContactsNoSimHelpTextWithSync); 127 } 128 } else { 129 if (hasIccCard()) { 130 setEmptyText(R.string.noContactsHelpText); 131 } else { 132 setEmptyText(R.string.noContactsNoSimHelpText); 133 } 134 } 135 } 136 137 public Uri getSelectedContactUri() { 138 return mSelectedContactUri; 139 } 140 141 public void setSelectedContactUri(Uri uri) { 142 if (mSelectedContactUri == null 143 || (mSelectedContactUri != null && !mSelectedContactUri.equals(uri))) { 144 mSelectedContactUri = uri; 145 146 parseSelectedContactUri(); 147 148 if (isAdded()) { 149 // Configure the adapter to show the selection based on the lookup key extracted 150 // from the URI 151 configureAdapter(); 152 153 // Also, launch a loader to pick up a new lookup key in case it has changed 154 startLoadingContactLookupKey(); 155 } 156 } 157 } 158 159 private void parseSelectedContactUri() { 160 if (mSelectedContactUri != null) { 161 if (!mSelectedContactUri.toString() 162 .startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { 163 throw new IllegalStateException( 164 "Contact list contains a non-lookup URI: " + mSelectedContactUri); 165 } 166 167 String directoryParam = 168 mSelectedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY); 169 mSelectedContactDirectoryId = TextUtils.isEmpty(directoryParam) 170 ? Directory.DEFAULT 171 : Long.parseLong(directoryParam); 172 mSelectedContactLookupKey = 173 Uri.encode(mSelectedContactUri.getPathSegments().get(2)); 174 } else { 175 mSelectedContactDirectoryId = Directory.DEFAULT; 176 mSelectedContactLookupKey = null; 177 } 178 } 179 180 @Override 181 protected void configureAdapter() { 182 super.configureAdapter(); 183 configureContactSelection(); 184 } 185 186 /** 187 * Configures the adapter with the identity of the currently selected contact. 188 */ 189 private void configureContactSelection() { 190 ContactListAdapter adapter = getAdapter(); 191 if (adapter == null) { 192 return; 193 } 194 195 adapter.setSelectedContact(mSelectedContactDirectoryId, mSelectedContactLookupKey); 196 } 197 198 public void setOnContactListActionListener(OnContactBrowserActionListener listener) { 199 mListener = listener; 200 } 201 202 public void createNewContact() { 203 mListener.onCreateNewContactAction(); 204 } 205 206 public void viewContact(Uri contactUri) { 207 mListener.onViewContactAction(contactUri); 208 } 209 210 public void editContact(Uri contactUri) { 211 mListener.onEditContactAction(contactUri); 212 } 213 214 public void deleteContact(Uri contactUri) { 215 mListener.onDeleteContactAction(contactUri); 216 } 217 218 public void addToFavorites(Uri contactUri) { 219 mListener.onAddToFavoritesAction(contactUri); 220 } 221 222 public void removeFromFavorites(Uri contactUri) { 223 mListener.onRemoveFromFavoritesAction(contactUri); 224 } 225 226 public void callContact(Uri contactUri) { 227 mListener.onCallContactAction(contactUri); 228 } 229 230 public void smsContact(Uri contactUri) { 231 mListener.onSmsContactAction(contactUri); 232 } 233 234 @Override 235 protected void finish() { 236 super.finish(); 237 mListener.onFinishAction(); 238 } 239 240 public void requestSelectionOnScreen(boolean smooth) { 241 mSelectionVisibilityRequest = smooth 242 ? SELECTION_VISIBILITY_REQUEST_SMOOTH 243 : SELECTION_VISIBILITY_REQUEST_INSTANT; 244 requestSelectionOnScreenIfNeeded(); 245 } 246 247 @Override 248 protected void completeRestoreInstanceState() { 249 super.completeRestoreInstanceState(); 250 requestSelectionOnScreenIfNeeded(); 251 } 252 253 private void requestSelectionOnScreenIfNeeded() { 254 if (mSelectionVisibilityRequest == SELECTION_VISIBILITY_REQUEST_NONE) { 255 return; 256 } 257 258 ContactListAdapter adapter = getAdapter(); 259 if (adapter == null) { 260 return; 261 } 262 263 int position = adapter.getSelectedContactPosition(); 264 if (position != -1) { 265 boolean smooth = mSelectionVisibilityRequest == SELECTION_VISIBILITY_REQUEST_SMOOTH; 266 mSelectionVisibilityRequest = SELECTION_VISIBILITY_REQUEST_NONE; 267 ListView listView = getListView(); 268 ListViewUtils.requestPositionToScreen( 269 listView, position + listView.getHeaderViewsCount(), smooth); 270 } 271 } 272} 273