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 */ 16 package com.android.contacts.common.list; 17 18 import android.content.Intent; 19 import android.content.Loader; 20 import android.database.Cursor; 21 import android.net.Uri; 22 import android.os.Bundle; 23 import android.text.TextUtils; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.MenuItem; 27 import android.view.View; 28 import android.view.View.OnClickListener; 29 import android.view.ViewGroup; 30 31 import com.android.contacts.common.R; 32 import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 33 import com.android.contacts.common.util.AccountFilterUtil; 34 35 /** 36 * Fragment containing a phone number list for picking. 37 */ 38 public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactEntryListAdapter> 39 implements OnShortcutIntentCreatedListener { 40 private static final String TAG = PhoneNumberPickerFragment.class.getSimpleName(); 41 42 private static final int REQUEST_CODE_ACCOUNT_FILTER = 1; 43 44 private static final String KEY_SHORTCUT_ACTION = "shortcutAction"; 45 46 private OnPhoneNumberPickerActionListener mListener; 47 private String mShortcutAction; 48 49 private ContactListFilter mFilter; 50 51 private View mAccountFilterHeader; 52 /** 53 * Lives as ListView's header and is shown when {@link #mAccountFilterHeader} is set 54 * to View.GONE. 55 */ 56 private View mPaddingView; 57 58 private static final String KEY_FILTER = "filter"; 59 60 /** true if the loader has started at least once. */ 61 private boolean mLoaderStarted; 62 63 private boolean mUseCallableUri; 64 65 private ContactListItemView.PhotoPosition mPhotoPosition = 66 ContactListItemView.getDefaultPhotoPosition(false /* normal/non opposite */); 67 68 private class FilterHeaderClickListener implements OnClickListener { 69 @Override onClick(View view)70 public void onClick(View view) { 71 AccountFilterUtil.startAccountFilterActivityForResult( 72 PhoneNumberPickerFragment.this, 73 REQUEST_CODE_ACCOUNT_FILTER, 74 mFilter); 75 } 76 } 77 private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener(); 78 PhoneNumberPickerFragment()79 public PhoneNumberPickerFragment() { 80 setQuickContactEnabled(false); 81 setPhotoLoaderEnabled(true); 82 setSectionHeaderDisplayEnabled(true); 83 setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE); 84 85 // Show nothing instead of letting caller Activity show something. 86 setHasOptionsMenu(true); 87 } 88 setDirectorySearchEnabled(boolean flag)89 public void setDirectorySearchEnabled(boolean flag) { 90 setDirectorySearchMode(flag ? DirectoryListLoader.SEARCH_MODE_DEFAULT 91 : DirectoryListLoader.SEARCH_MODE_NONE); 92 } 93 setOnPhoneNumberPickerActionListener(OnPhoneNumberPickerActionListener listener)94 public void setOnPhoneNumberPickerActionListener(OnPhoneNumberPickerActionListener listener) { 95 this.mListener = listener; 96 } 97 getOnPhoneNumberPickerListener()98 public OnPhoneNumberPickerActionListener getOnPhoneNumberPickerListener() { 99 return mListener; 100 } 101 102 @Override onCreateView(LayoutInflater inflater, ViewGroup container)103 protected void onCreateView(LayoutInflater inflater, ViewGroup container) { 104 super.onCreateView(inflater, container); 105 106 View paddingView = inflater.inflate(R.layout.contact_detail_list_padding, null, false); 107 mPaddingView = paddingView.findViewById(R.id.contact_detail_list_padding); 108 getListView().addHeaderView(paddingView); 109 110 mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container); 111 mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener); 112 updateFilterHeaderView(); 113 114 setVisibleScrollbarEnabled(getVisibleScrollbarEnabled()); 115 } 116 getVisibleScrollbarEnabled()117 protected boolean getVisibleScrollbarEnabled() { 118 return true; 119 } 120 121 @Override setSearchMode(boolean flag)122 protected void setSearchMode(boolean flag) { 123 super.setSearchMode(flag); 124 updateFilterHeaderView(); 125 } 126 updateFilterHeaderView()127 private void updateFilterHeaderView() { 128 final ContactListFilter filter = getFilter(); 129 if (mAccountFilterHeader == null || filter == null) { 130 return; 131 } 132 final boolean shouldShowHeader = 133 !isSearchMode() && 134 AccountFilterUtil.updateAccountFilterTitleForPhone( 135 mAccountFilterHeader, filter, false); 136 if (shouldShowHeader) { 137 mPaddingView.setVisibility(View.GONE); 138 mAccountFilterHeader.setVisibility(View.VISIBLE); 139 } else { 140 mPaddingView.setVisibility(View.VISIBLE); 141 mAccountFilterHeader.setVisibility(View.GONE); 142 } 143 } 144 145 @Override restoreSavedState(Bundle savedState)146 public void restoreSavedState(Bundle savedState) { 147 super.restoreSavedState(savedState); 148 149 if (savedState == null) { 150 return; 151 } 152 153 mFilter = savedState.getParcelable(KEY_FILTER); 154 mShortcutAction = savedState.getString(KEY_SHORTCUT_ACTION); 155 } 156 157 @Override onSaveInstanceState(Bundle outState)158 public void onSaveInstanceState(Bundle outState) { 159 super.onSaveInstanceState(outState); 160 outState.putParcelable(KEY_FILTER, mFilter); 161 outState.putString(KEY_SHORTCUT_ACTION, mShortcutAction); 162 } 163 164 @Override onOptionsItemSelected(MenuItem item)165 public boolean onOptionsItemSelected(MenuItem item) { 166 final int itemId = item.getItemId(); 167 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled() 168 if (mListener != null) { 169 mListener.onHomeInActionBarSelected(); 170 } 171 return true; 172 } 173 return super.onOptionsItemSelected(item); 174 } 175 176 /** 177 * @param shortcutAction either {@link Intent#ACTION_CALL} or 178 * {@link Intent#ACTION_SENDTO} or null. 179 */ setShortcutAction(String shortcutAction)180 public void setShortcutAction(String shortcutAction) { 181 this.mShortcutAction = shortcutAction; 182 } 183 184 @Override onItemClick(int position, long id)185 protected void onItemClick(int position, long id) { 186 final Uri phoneUri = getPhoneUri(position); 187 188 if (phoneUri != null) { 189 pickPhoneNumber(phoneUri); 190 } else { 191 final String number = getPhoneNumber(position); 192 if (!TextUtils.isEmpty(number)) { 193 cacheContactInfo(position); 194 mListener.onCallNumberDirectly(number); 195 } else { 196 Log.w(TAG, "Item at " + position + " was clicked before" 197 + " adapter is ready. Ignoring"); 198 } 199 } 200 } 201 cacheContactInfo(int position)202 protected void cacheContactInfo(int position) { 203 // Not implemented. Hook for child classes 204 } 205 getPhoneNumber(int position)206 protected String getPhoneNumber(int position) { 207 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 208 return adapter.getPhoneNumber(position); 209 } 210 getPhoneUri(int position)211 protected Uri getPhoneUri(int position) { 212 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 213 return adapter.getDataUri(position); 214 } 215 216 @Override startLoading()217 protected void startLoading() { 218 mLoaderStarted = true; 219 super.startLoading(); 220 } 221 222 @Override onLoadFinished(Loader<Cursor> loader, Cursor data)223 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 224 super.onLoadFinished(loader, data); 225 226 // disable scroll bar if there is no data 227 setVisibleScrollbarEnabled(data != null && data.getCount() > 0); 228 } 229 setUseCallableUri(boolean useCallableUri)230 public void setUseCallableUri(boolean useCallableUri) { 231 mUseCallableUri = useCallableUri; 232 } 233 usesCallableUri()234 public boolean usesCallableUri() { 235 return mUseCallableUri; 236 } 237 238 @Override createListAdapter()239 protected ContactEntryListAdapter createListAdapter() { 240 PhoneNumberListAdapter adapter = new PhoneNumberListAdapter(getActivity()); 241 adapter.setDisplayPhotos(true); 242 adapter.setUseCallableUri(mUseCallableUri); 243 return adapter; 244 } 245 246 @Override configureAdapter()247 protected void configureAdapter() { 248 super.configureAdapter(); 249 250 final ContactEntryListAdapter adapter = getAdapter(); 251 if (adapter == null) { 252 return; 253 } 254 255 if (!isSearchMode() && mFilter != null) { 256 adapter.setFilter(mFilter); 257 } 258 259 setPhotoPosition(adapter); 260 } 261 setPhotoPosition(ContactEntryListAdapter adapter)262 protected void setPhotoPosition(ContactEntryListAdapter adapter) { 263 ((PhoneNumberListAdapter) adapter).setPhotoPosition(mPhotoPosition); 264 } 265 266 @Override inflateView(LayoutInflater inflater, ViewGroup container)267 protected View inflateView(LayoutInflater inflater, ViewGroup container) { 268 return inflater.inflate(R.layout.contact_list_content, null); 269 } 270 pickPhoneNumber(Uri uri)271 public void pickPhoneNumber(Uri uri) { 272 if (mShortcutAction == null) { 273 mListener.onPickPhoneNumberAction(uri); 274 } else { 275 startPhoneNumberShortcutIntent(uri); 276 } 277 } 278 startPhoneNumberShortcutIntent(Uri uri)279 protected void startPhoneNumberShortcutIntent(Uri uri) { 280 ShortcutIntentBuilder builder = new ShortcutIntentBuilder(getActivity(), this); 281 builder.createPhoneNumberShortcutIntent(uri, mShortcutAction); 282 } 283 onShortcutIntentCreated(Uri uri, Intent shortcutIntent)284 public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 285 mListener.onShortcutIntentCreated(shortcutIntent); 286 } 287 288 @Override onPickerResult(Intent data)289 public void onPickerResult(Intent data) { 290 mListener.onPickPhoneNumberAction(data.getData()); 291 } 292 293 @Override onActivityResult(int requestCode, int resultCode, Intent data)294 public void onActivityResult(int requestCode, int resultCode, Intent data) { 295 if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) { 296 if (getActivity() != null) { 297 AccountFilterUtil.handleAccountFilterResult( 298 ContactListFilterController.getInstance(getActivity()), resultCode, data); 299 } else { 300 Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()"); 301 } 302 } 303 } 304 getFilter()305 public ContactListFilter getFilter() { 306 return mFilter; 307 } 308 setFilter(ContactListFilter filter)309 public void setFilter(ContactListFilter filter) { 310 if ((mFilter == null && filter == null) || 311 (mFilter != null && mFilter.equals(filter))) { 312 return; 313 } 314 315 mFilter = filter; 316 if (mLoaderStarted) { 317 reloadData(); 318 } 319 updateFilterHeaderView(); 320 } 321 setPhotoPosition(ContactListItemView.PhotoPosition photoPosition)322 public void setPhotoPosition(ContactListItemView.PhotoPosition photoPosition) { 323 mPhotoPosition = photoPosition; 324 325 final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter(); 326 if (adapter != null) { 327 adapter.setPhotoPosition(photoPosition); 328 } 329 } 330 } 331