DialtactsActivity.java revision b2e626ad4fedc0fd726f66b9942d1b2f30d9cfef
1/* 2 * Copyright (C) 2008 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 17package com.android.contacts.activities; 18 19import com.android.contacts.R; 20import com.android.contacts.calllog.CallLogFragment; 21import com.android.contacts.dialpad.DialpadFragment; 22import com.android.contacts.interactions.ImportExportDialogFragment; 23import com.android.contacts.interactions.PhoneNumberInteraction; 24import com.android.contacts.list.ContactListFilter; 25import com.android.contacts.list.ContactsIntentResolver; 26import com.android.contacts.list.ContactsRequest; 27import com.android.contacts.list.DefaultContactBrowseListFragment; 28import com.android.contacts.list.DirectoryListLoader; 29import com.android.contacts.list.OnContactBrowserActionListener; 30import com.android.contacts.list.OnPhoneNumberPickerActionListener; 31import com.android.contacts.list.PhoneNumberPickerFragment; 32import com.android.contacts.list.StrequentContactListFragment; 33import com.android.contacts.preference.ContactsPreferenceActivity; 34import com.android.internal.telephony.ITelephony; 35 36import android.app.ActionBar; 37import android.app.ActionBar.LayoutParams; 38import android.app.ActionBar.Tab; 39import android.app.ActionBar.TabListener; 40import android.app.Activity; 41import android.app.Fragment; 42import android.app.FragmentManager; 43import android.app.FragmentTransaction; 44import android.content.Intent; 45import android.content.SharedPreferences; 46import android.net.Uri; 47import android.os.Bundle; 48import android.os.RemoteException; 49import android.os.ServiceManager; 50import android.provider.CallLog.Calls; 51import android.provider.ContactsContract; 52import android.provider.ContactsContract.Contacts; 53import android.provider.ContactsContract.Intents.UI; 54import android.provider.Settings; 55import android.text.TextUtils; 56import android.util.Log; 57import android.view.Menu; 58import android.view.MenuInflater; 59import android.view.MenuItem; 60import android.view.View; 61import android.widget.SearchView; 62import android.widget.SearchView.OnCloseListener; 63import android.widget.SearchView.OnQueryTextListener; 64 65/** 66 * The dialer activity that has one tab with the virtual 12key 67 * dialer, a tab with recent calls in it, a tab with the contacts and 68 * a tab with the favorite. This is the container and the tabs are 69 * embedded using intents. 70 * The dialer tab's title is 'phone', a more common name (see strings.xml). 71 */ 72public class DialtactsActivity extends Activity { 73 private static final String TAG = "DialtactsActivity"; 74 75 private static final int TAB_INDEX_DIALER = 0; 76 private static final int TAB_INDEX_CALL_LOG = 1; 77 private static final int TAB_INDEX_CONTACTS = 2; 78 private static final int TAB_INDEX_FAVORITES = 3; 79 80 public static final String EXTRA_IGNORE_STATE = "ignore-state"; 81 82 /** Name of the dialtacts shared preferences */ 83 static final String PREFS_DIALTACTS = "dialtacts"; 84 /** If true, when handling the contacts intent the favorites tab will be shown instead */ 85 static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts"; 86 static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false; 87 88 /** Last manually selected tab index */ 89 private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab"; 90 private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER; 91 92 private String mFilterText; 93 private Uri mDialUri; 94 private DialpadFragment mDialpadFragment; 95 private CallLogFragment mCallLogFragment; 96 private DefaultContactBrowseListFragment mContactsFragment; 97 private StrequentContactListFragment mStrequentFragment; 98 99 /** 100 * The index of the tab that has last been manually selected (the user clicked on a tab). 101 * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call) 102 */ 103 private int mLastManuallySelectedTab; 104 105 /** 106 * Fragment for searching phone numbers. Unlike the other Fragments, this doesn't correspond 107 * to tab but is shown by a search action. 108 */ 109 private PhoneNumberPickerFragment mPhoneNumberPickerFragment; 110 111 private SearchView mSearchView; 112 113 /** 114 * True when this Activity is in its search UI (with a {@link SearchView} and 115 * {@link PhoneNumberPickerFragment}). 116 */ 117 private boolean mInSearchUi; 118 119 /** 120 * Listener used when one of phone numbers in search UI is selected. This will initiate a 121 * phone call using the phone number. 122 */ 123 private final OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener = 124 new OnPhoneNumberPickerActionListener() { 125 @Override 126 public void onPickPhoneNumberAction(Uri dataUri) { 127 PhoneNumberInteraction.startInteractionForPhoneCall( 128 DialtactsActivity.this, dataUri); 129 } 130 131 @Override 132 public void onShortcutIntentCreated(Intent intent) { 133 Log.w(TAG, "Unsupported intent has come (" + intent + "). Ignoring."); 134 } 135 }; 136 137 /** 138 * Listener used to send search queries to the phone search fragment. 139 */ 140 private final OnQueryTextListener mPhoneSearchQueryTextListener = 141 new OnQueryTextListener() { 142 @Override 143 public boolean onQueryTextSubmit(String query) { 144 // Ignore. 145 return true; 146 } 147 148 @Override 149 public boolean onQueryTextChange(String newText) { 150 // Show search result with non-empty text. Show a bare list otherwise. 151 mPhoneNumberPickerFragment.setQueryString(newText, true); 152 mPhoneNumberPickerFragment.setSearchMode(!TextUtils.isEmpty(newText)); 153 return true; 154 } 155 }; 156 157 /** 158 * Listener used to handle the "close" button on the right side of {@link SearchView}. 159 * If some text is in the search view, this will clean it up. Otherwise this will exit 160 * the search UI and let users go back to usual Phone UI. 161 * 162 * This does _not_ handle back button. 163 * 164 * TODO: need "up" button instead of close button 165 */ 166 private final OnCloseListener mPhoneSearchCloseListener = 167 new OnCloseListener() { 168 @Override 169 public boolean onClose() { 170 if (TextUtils.isEmpty(mSearchView.getQuery())) { 171 exitSearchUi(); 172 } else { 173 mSearchView.setQuery(null, true); 174 } 175 return true; 176 } 177 }; 178 179 @Override 180 protected void onCreate(Bundle icicle) { 181 super.onCreate(icicle); 182 183 final Intent intent = getIntent(); 184 fixIntent(intent); 185 186 setContentView(R.layout.dialtacts_activity); 187 188 final FragmentManager fragmentManager = getFragmentManager(); 189 mDialpadFragment = (DialpadFragment) fragmentManager 190 .findFragmentById(R.id.dialpad_fragment); 191 mCallLogFragment = (CallLogFragment) fragmentManager 192 .findFragmentById(R.id.call_log_fragment); 193 mContactsFragment = (DefaultContactBrowseListFragment) fragmentManager 194 .findFragmentById(R.id.contacts_fragment); 195 mStrequentFragment = (StrequentContactListFragment) fragmentManager 196 .findFragmentById(R.id.favorites_fragment); 197 mPhoneNumberPickerFragment = (PhoneNumberPickerFragment) fragmentManager 198 .findFragmentById(R.id.phone_number_picker_fragment); 199 mPhoneNumberPickerFragment.setOnPhoneNumberPickerActionListener( 200 mPhoneNumberPickerActionListener); 201 202 // Hide all tabs (the current tab will later be reshown once a tab is selected) 203 final FragmentTransaction transaction = fragmentManager.beginTransaction(); 204 transaction.hide(mDialpadFragment); 205 transaction.hide(mCallLogFragment); 206 transaction.hide(mContactsFragment); 207 transaction.hide(mStrequentFragment); 208 transaction.hide(mPhoneNumberPickerFragment); 209 transaction.commit(); 210 211 // Setup the ActionBar tabs (the order matches the tab-index contants TAB_INDEX_*) 212 setupDialer(); 213 setupCallLog(); 214 setupContacts(); 215 setupFavorites(); 216 getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 217 getActionBar().setDisplayShowTitleEnabled(false); 218 getActionBar().setDisplayShowHomeEnabled(false); 219 220 // Load the last manually loaded tab 221 final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE); 222 mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB, 223 PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT); 224 225 setCurrentTab(intent); 226 227 if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction()) 228 && icicle == null) { 229 setupFilterText(intent); 230 } 231 } 232 233 @Override 234 protected void onPause() { 235 super.onPause(); 236 237 final SharedPreferences.Editor editor = 238 getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit(); 239 // selectedTab becomes null in search UI. 240 final Tab selectedTab = getActionBar().getSelectedTab(); 241 if (selectedTab != null) { 242 final int currentTabIndex = selectedTab.getPosition(); 243 if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) { 244 editor.putBoolean( 245 PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES); 246 } 247 } 248 editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab); 249 250 editor.apply(); 251 } 252 253 private void fixIntent(Intent intent) { 254 // This should be cleaned up: the call key used to send an Intent 255 // that just said to go to the recent calls list. It now sends this 256 // abstract action, but this class hasn't been rewritten to deal with it. 257 if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) { 258 intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE); 259 intent.putExtra("call_key", true); 260 setIntent(intent); 261 } 262 } 263 264 private void setupDialer() { 265 final Tab tab = getActionBar().newTab(); 266 // TODO: Temporarily disable tab text labels (in all 4 tabs in this 267 // activity) so that the current tabs will all fit onscreen in 268 // portrait (bug 4520620). (Also note we do setText("") rather 269 // leaving the text null, to work around bug 4521549.) 270 tab.setText(""); // R.string.dialerIconLabel 271 tab.setTabListener(new TabChangeListener(mDialpadFragment)); 272 tab.setIcon(R.drawable.ic_tab_dialer); 273 getActionBar().addTab(tab); 274 mDialpadFragment.resolveIntent(); 275 } 276 277 private void setupCallLog() { 278 final Tab tab = getActionBar().newTab(); 279 tab.setText(""); // R.string.recentCallsIconLabel 280 tab.setIcon(R.drawable.ic_tab_recent); 281 tab.setTabListener(new TabChangeListener(mCallLogFragment)); 282 getActionBar().addTab(tab); 283 } 284 285 private void setupContacts() { 286 final Tab tab = getActionBar().newTab(); 287 tab.setText(""); // R.string.contactsIconLabel 288 tab.setIcon(R.drawable.ic_tab_contacts); 289 tab.setTabListener(new TabChangeListener(mContactsFragment)); 290 getActionBar().addTab(tab); 291 292 // TODO: We should not artificially create Intents and put them into the Fragment. 293 // It would be nicer to directly pass in the UI constant 294 Intent intent = new Intent(UI.LIST_ALL_CONTACTS_ACTION); 295 intent.setClass(this, PeopleActivity.class); 296 297 ContactsIntentResolver resolver = new ContactsIntentResolver(this); 298 ContactsRequest request = resolver.resolveIntent(intent); 299 final ContactListFilter filter = ContactListFilter.createFilterWithType( 300 ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS); 301 mContactsFragment.setFilter(filter, false); 302 mContactsFragment.setSearchMode(request.isSearchMode()); 303 mContactsFragment.setQueryString(request.getQueryString(), false); 304 mContactsFragment.setContactsRequest(request); 305 mContactsFragment.setDirectorySearchMode(request.isDirectorySearchEnabled() 306 ? DirectoryListLoader.SEARCH_MODE_DEFAULT 307 : DirectoryListLoader.SEARCH_MODE_NONE); 308 mContactsFragment.setOnContactListActionListener(mListFragmentListener); 309 } 310 311 private void setupFavorites() { 312 final Tab tab = getActionBar().newTab(); 313 tab.setText(""); // R.string.contactsFavoritesLabel 314 tab.setIcon(R.drawable.ic_tab_starred); 315 tab.setTabListener(new TabChangeListener(mStrequentFragment)); 316 getActionBar().addTab(tab); 317 mStrequentFragment.setListener(mStrequentListener); 318 } 319 320 /** 321 * Returns true if the intent is due to hitting the green send key while in a call. 322 * 323 * @param intent the intent that launched this activity 324 * @param recentCallsRequest true if the intent is requesting to view recent calls 325 * @return true if the intent is due to hitting the green send key while in a call 326 */ 327 private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) { 328 // If there is a call in progress go to the call screen 329 if (recentCallsRequest) { 330 final boolean callKey = intent.getBooleanExtra("call_key", false); 331 332 try { 333 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 334 if (callKey && phone != null && phone.showCallScreen()) { 335 return true; 336 } 337 } catch (RemoteException e) { 338 Log.e(TAG, "Failed to handle send while in call", e); 339 } 340 } 341 342 return false; 343 } 344 345 /** 346 * Sets the current tab based on the intent's request type 347 * 348 * @param intent Intent that contains information about which tab should be selected 349 */ 350 private void setCurrentTab(Intent intent) { 351 // If we got here by hitting send and we're in call forward along to the in-call activity 352 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType()); 353 if (isSendKeyWhileInCall(intent, recentCallsRequest)) { 354 finish(); 355 return; 356 } 357 358 // Tell the children activities that they should ignore any possible saved 359 // state and instead reload their state from the parent's intent 360 intent.putExtra(EXTRA_IGNORE_STATE, true); 361 362 // Remember the old manually selected tab index so that it can be restored if it is 363 // overwritten by one of the programmatic tab selections 364 final int savedTabIndex = mLastManuallySelectedTab; 365 366 // Look at the component to determine the tab 367 String componentName = intent.getComponent().getClassName(); 368 if (getClass().getName().equals(componentName)) { 369 if (recentCallsRequest) { 370 getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_CALL_LOG)); 371 } else { 372 getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_DIALER)); 373 } 374 } else { 375 getActionBar().selectTab(getActionBar().getTabAt(mLastManuallySelectedTab)); 376 } 377 378 // Restore to the previous manual selection 379 mLastManuallySelectedTab = savedTabIndex; 380 381 // Tell the children activities that they should honor their saved states 382 // instead of the state from the parent's intent 383 intent.putExtra(EXTRA_IGNORE_STATE, false); 384 } 385 386 @Override 387 public void onNewIntent(Intent newIntent) { 388 setIntent(newIntent); 389 fixIntent(newIntent); 390 setCurrentTab(newIntent); 391 final String action = newIntent.getAction(); 392 if (UI.FILTER_CONTACTS_ACTION.equals(action)) { 393 setupFilterText(newIntent); 394 } else if (isDialIntent(newIntent)) { 395 setupDialUri(newIntent); 396 } 397 // Fill in a phone number again. 398 mDialpadFragment.resolveIntent(); 399 } 400 401 /** Returns true if the given intent contains a phone number to populate the dialer with */ 402 private boolean isDialIntent(Intent intent) { 403 final String action = intent.getAction(); 404 if (Intent.ACTION_DIAL.equals(action)) { 405 return true; 406 } 407 if (Intent.ACTION_VIEW.equals(action)) { 408 final Uri data = intent.getData(); 409 if (data != null && "tel".equals(data.getScheme())) { 410 return true; 411 } 412 } 413 return false; 414 } 415 416 /** 417 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 418 * This text originally came from a FILTER_CONTACTS_ACTION intent received 419 * by this activity. The stored text will then be cleared after after this 420 * method returns. 421 * 422 * @return The stored filter text 423 */ 424 public String getAndClearFilterText() { 425 String filterText = mFilterText; 426 mFilterText = null; 427 return filterText; 428 } 429 430 /** 431 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 432 * This is so child activities can check if they are supposed to display a filter. 433 * 434 * @param intent The intent received in {@link #onNewIntent(Intent)} 435 */ 436 private void setupFilterText(Intent intent) { 437 // If the intent was relaunched from history, don't apply the filter text. 438 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 439 return; 440 } 441 String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY); 442 if (filter != null && filter.length() > 0) { 443 mFilterText = filter; 444 } 445 } 446 447 /** 448 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 449 * originally came from a dial intent received by this activity. The stored 450 * uri will then be cleared after after this method returns. 451 * 452 * @return The stored uri 453 */ 454 public Uri getAndClearDialUri() { 455 Uri dialUri = mDialUri; 456 mDialUri = null; 457 return dialUri; 458 } 459 460 /** 461 * Stores the uri associated with a dial intent. This is so child activities can 462 * check if they are supposed to display new dial info. 463 * 464 * @param intent The intent received in {@link #onNewIntent(Intent)} 465 */ 466 private void setupDialUri(Intent intent) { 467 // If the intent was relaunched from history, don't reapply the intent. 468 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 469 return; 470 } 471 mDialUri = intent.getData(); 472 } 473 474 @Override 475 public void onBackPressed() { 476 if (mInSearchUi) { 477 // We should let the user go back to usual screens with tabs. 478 exitSearchUi(); 479 } else if (isTaskRoot()) { 480 // Instead of stopping, simply push this to the back of the stack. 481 // This is only done when running at the top of the stack; 482 // otherwise, we have been launched by someone else so need to 483 // allow the user to go back to the caller. 484 moveTaskToBack(false); 485 } else { 486 super.onBackPressed(); 487 } 488 } 489 490 @Override 491 protected void onPostCreate(Bundle savedInstanceState) { 492 super.onPostCreate(savedInstanceState); 493 494 // Pass this lifecycle event down to the fragment 495 mDialpadFragment.onPostCreate(); 496 } 497 498 /** 499 * Tab change listener that is instantiated once for each tab. Handles showing/hiding tabs 500 * and remembers manual tab selections 501 */ 502 private class TabChangeListener implements TabListener { 503 private final Fragment mFragment; 504 505 public TabChangeListener(Fragment fragment) { 506 mFragment = fragment; 507 } 508 509 @Override 510 public void onTabUnselected(Tab tab, FragmentTransaction ft) { 511 ft.hide(mFragment); 512 } 513 514 @Override 515 public void onTabSelected(Tab tab, FragmentTransaction ft) { 516 ft.show(mFragment); 517 ft.hide(mPhoneNumberPickerFragment); 518 519 // Remember this tab index. This function is also called, if the tab is set 520 // automatically in which case the setter (setCurrentTab) has to set this to its old 521 // value afterwards 522 mLastManuallySelectedTab = tab.getPosition(); 523 } 524 525 @Override 526 public void onTabReselected(Tab tab, FragmentTransaction ft) { 527 } 528 } 529 530 private OnContactBrowserActionListener mListFragmentListener = 531 new OnContactBrowserActionListener() { 532 @Override 533 public void onViewContactAction(Uri contactLookupUri) { 534 startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri)); 535 } 536 537 @Override 538 public void onSmsContactAction(Uri contactUri) { 539 } 540 541 @Override 542 public void onSelectionChange() { 543 } 544 545 @Override 546 public void onRemoveFromFavoritesAction(Uri contactUri) { 547 } 548 549 @Override 550 public void onInvalidSelection() { 551 } 552 553 @Override 554 public void onFinishAction() { 555 } 556 557 @Override 558 public void onEditContactAction(Uri contactLookupUri) { 559 } 560 561 @Override 562 public void onDeleteContactAction(Uri contactUri) { 563 } 564 565 @Override 566 public void onCreateNewContactAction() { 567 } 568 569 @Override 570 public void onCallContactAction(Uri contactUri) { 571 PhoneNumberInteraction.startInteractionForPhoneCall( 572 DialtactsActivity.this, contactUri); 573 } 574 575 @Override 576 public void onAddToFavoritesAction(Uri contactUri) { 577 } 578 }; 579 580 private StrequentContactListFragment.Listener mStrequentListener = 581 new StrequentContactListFragment.Listener() { 582 @Override 583 public void onContactSelected(Uri contactUri) { 584 PhoneNumberInteraction.startInteractionForPhoneCall( 585 DialtactsActivity.this, contactUri); 586 } 587 }; 588 589 @Override 590 public boolean onCreateOptionsMenu(Menu menu) { 591 // For now, create the menu in here. It would be nice to do this in the Fragment, 592 // but that Fragment is re-used in other views. 593 final ActionBar actionBar = getActionBar(); 594 if (actionBar == null) return false; 595 final Tab tab = actionBar.getSelectedTab(); 596 if (tab == null) return false; 597 final int tabIndex = tab.getPosition(); 598 if (tabIndex != TAB_INDEX_CONTACTS && tabIndex != TAB_INDEX_FAVORITES) return false; 599 600 MenuInflater inflater = getMenuInflater(); 601 inflater.inflate(R.menu.list, menu); 602 return true; 603 } 604 605 @Override 606 public boolean onOptionsItemSelected(MenuItem item) { 607 // This is currently a copy of the equivalent code of PeopleActivity (with the 608 // exception of menu_add, because we do not select items in the list). 609 // Should be consolidated 610 switch (item.getItemId()) { 611 case R.id.menu_settings: { 612 final Intent intent = new Intent(this, ContactsPreferenceActivity.class); 613 startActivity(intent); 614 return true; 615 } 616 case R.id.menu_search: { 617 onSearchRequested(); 618 return true; 619 } 620 case R.id.menu_add: { 621 final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); 622 startActivity(intent); 623 return true; 624 } 625 case R.id.menu_import_export: { 626 ImportExportDialogFragment.show(getFragmentManager()); 627 return true; 628 } 629 case R.id.menu_accounts: { 630 final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS); 631 intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] { 632 ContactsContract.AUTHORITY 633 }); 634 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 635 startActivity(intent); 636 return true; 637 } 638 default: 639 return super.onOptionsItemSelected(item); 640 } 641 } 642 643 @Override 644 public void startSearch(String initialQuery, boolean selectInitialQuery, 645 Bundle appSearchData, boolean globalSearch) { 646 if (mPhoneNumberPickerFragment != null && mPhoneNumberPickerFragment.isAdded() 647 && !globalSearch) { 648 enterSearchUi(); 649 } else { 650 super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch); 651 } 652 } 653 654 /** 655 * Hides every tab and shows search UI for phone lookup. 656 */ 657 private void enterSearchUi() { 658 final ActionBar actionBar = getActionBar(); 659 660 final Tab tab = actionBar.getSelectedTab(); 661 if (tab != null) { 662 mLastManuallySelectedTab = tab.getPosition(); 663 } 664 665 // Instantiate or reset SearchView in ActionBar. 666 if (mSearchView == null) { 667 // TODO: layout is not what we want. Need "up" button instead of "close" button, etc. 668 final View searchViewLayout = 669 getLayoutInflater().inflate(R.layout.custom_action_bar, null); 670 mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view); 671 mSearchView.setQueryHint(getString(R.string.hint_findContacts)); 672 mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener); 673 mSearchView.setOnCloseListener(mPhoneSearchCloseListener); 674 mSearchView.requestFocus(); 675 actionBar.setCustomView(searchViewLayout, 676 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 677 } else { 678 mSearchView.setQuery(null, true); 679 } 680 681 actionBar.setDisplayShowCustomEnabled(true); 682 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 683 684 // Show the search fragment and hide everything else. 685 final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 686 transaction.show(mPhoneNumberPickerFragment); 687 transaction.hide(mDialpadFragment); 688 transaction.hide(mCallLogFragment); 689 transaction.hide(mContactsFragment); 690 transaction.hide(mStrequentFragment); 691 transaction.commit(); 692 693 mInSearchUi = true; 694 } 695 696 /** 697 * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment 698 * should be automatically focused again. 699 */ 700 private void exitSearchUi() { 701 final ActionBar actionBar = getActionBar(); 702 703 // We want to hide SearchView and show Tabs. Also focus on previously selected one. 704 actionBar.setDisplayShowCustomEnabled(false); 705 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 706 707 mInSearchUi = false; 708 } 709} 710