DialtactsActivity.java revision 350e8d53a135e0bb62308a93dd09777364c08a58
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 if (recentCallsRequest) { 367 getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_CALL_LOG)); 368 } else { 369 getActionBar().selectTab(getActionBar().getTabAt(mLastManuallySelectedTab)); 370 } 371 372 // Restore to the previous manual selection 373 mLastManuallySelectedTab = savedTabIndex; 374 375 // Tell the children activities that they should honor their saved states 376 // instead of the state from the parent's intent 377 intent.putExtra(EXTRA_IGNORE_STATE, false); 378 } 379 380 @Override 381 public void onNewIntent(Intent newIntent) { 382 setIntent(newIntent); 383 fixIntent(newIntent); 384 setCurrentTab(newIntent); 385 final String action = newIntent.getAction(); 386 if (UI.FILTER_CONTACTS_ACTION.equals(action)) { 387 setupFilterText(newIntent); 388 } else if (isDialIntent(newIntent)) { 389 setupDialUri(newIntent); 390 } 391 // Fill in a phone number again. 392 mDialpadFragment.resolveIntent(); 393 } 394 395 /** Returns true if the given intent contains a phone number to populate the dialer with */ 396 private boolean isDialIntent(Intent intent) { 397 final String action = intent.getAction(); 398 if (Intent.ACTION_DIAL.equals(action)) { 399 return true; 400 } 401 if (Intent.ACTION_VIEW.equals(action)) { 402 final Uri data = intent.getData(); 403 if (data != null && "tel".equals(data.getScheme())) { 404 return true; 405 } 406 } 407 return false; 408 } 409 410 /** 411 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}. 412 * This text originally came from a FILTER_CONTACTS_ACTION intent received 413 * by this activity. The stored text will then be cleared after after this 414 * method returns. 415 * 416 * @return The stored filter text 417 */ 418 public String getAndClearFilterText() { 419 String filterText = mFilterText; 420 mFilterText = null; 421 return filterText; 422 } 423 424 /** 425 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent. 426 * This is so child activities can check if they are supposed to display a filter. 427 * 428 * @param intent The intent received in {@link #onNewIntent(Intent)} 429 */ 430 private void setupFilterText(Intent intent) { 431 // If the intent was relaunched from history, don't apply the filter text. 432 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 433 return; 434 } 435 String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY); 436 if (filter != null && filter.length() > 0) { 437 mFilterText = filter; 438 } 439 } 440 441 /** 442 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri 443 * originally came from a dial intent received by this activity. The stored 444 * uri will then be cleared after after this method returns. 445 * 446 * @return The stored uri 447 */ 448 public Uri getAndClearDialUri() { 449 Uri dialUri = mDialUri; 450 mDialUri = null; 451 return dialUri; 452 } 453 454 /** 455 * Stores the uri associated with a dial intent. This is so child activities can 456 * check if they are supposed to display new dial info. 457 * 458 * @param intent The intent received in {@link #onNewIntent(Intent)} 459 */ 460 private void setupDialUri(Intent intent) { 461 // If the intent was relaunched from history, don't reapply the intent. 462 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { 463 return; 464 } 465 mDialUri = intent.getData(); 466 } 467 468 @Override 469 public void onBackPressed() { 470 if (mInSearchUi) { 471 // We should let the user go back to usual screens with tabs. 472 exitSearchUi(); 473 } else if (isTaskRoot()) { 474 // Instead of stopping, simply push this to the back of the stack. 475 // This is only done when running at the top of the stack; 476 // otherwise, we have been launched by someone else so need to 477 // allow the user to go back to the caller. 478 moveTaskToBack(false); 479 } else { 480 super.onBackPressed(); 481 } 482 } 483 484 @Override 485 protected void onPostCreate(Bundle savedInstanceState) { 486 super.onPostCreate(savedInstanceState); 487 488 // Pass this lifecycle event down to the fragment 489 mDialpadFragment.onPostCreate(); 490 } 491 492 /** 493 * Tab change listener that is instantiated once for each tab. Handles showing/hiding tabs 494 * and remembers manual tab selections 495 */ 496 private class TabChangeListener implements TabListener { 497 private final Fragment mFragment; 498 499 public TabChangeListener(Fragment fragment) { 500 mFragment = fragment; 501 } 502 503 @Override 504 public void onTabUnselected(Tab tab, FragmentTransaction ft) { 505 ft.hide(mFragment); 506 } 507 508 @Override 509 public void onTabSelected(Tab tab, FragmentTransaction ft) { 510 ft.show(mFragment); 511 ft.hide(mPhoneNumberPickerFragment); 512 513 // Remember this tab index. This function is also called, if the tab is set 514 // automatically in which case the setter (setCurrentTab) has to set this to its old 515 // value afterwards 516 mLastManuallySelectedTab = tab.getPosition(); 517 } 518 519 @Override 520 public void onTabReselected(Tab tab, FragmentTransaction ft) { 521 } 522 } 523 524 private OnContactBrowserActionListener mListFragmentListener = 525 new OnContactBrowserActionListener() { 526 @Override 527 public void onViewContactAction(Uri contactLookupUri) { 528 startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri)); 529 } 530 531 @Override 532 public void onSmsContactAction(Uri contactUri) { 533 } 534 535 @Override 536 public void onSelectionChange() { 537 } 538 539 @Override 540 public void onRemoveFromFavoritesAction(Uri contactUri) { 541 } 542 543 @Override 544 public void onInvalidSelection() { 545 } 546 547 @Override 548 public void onFinishAction() { 549 } 550 551 @Override 552 public void onEditContactAction(Uri contactLookupUri) { 553 } 554 555 @Override 556 public void onDeleteContactAction(Uri contactUri) { 557 } 558 559 @Override 560 public void onCreateNewContactAction() { 561 } 562 563 @Override 564 public void onCallContactAction(Uri contactUri) { 565 PhoneNumberInteraction.startInteractionForPhoneCall( 566 DialtactsActivity.this, contactUri); 567 } 568 569 @Override 570 public void onAddToFavoritesAction(Uri contactUri) { 571 } 572 }; 573 574 private StrequentContactListFragment.Listener mStrequentListener = 575 new StrequentContactListFragment.Listener() { 576 @Override 577 public void onContactSelected(Uri contactUri) { 578 PhoneNumberInteraction.startInteractionForPhoneCall( 579 DialtactsActivity.this, contactUri); 580 } 581 }; 582 583 @Override 584 public boolean onCreateOptionsMenu(Menu menu) { 585 // For now, create the menu in here. It would be nice to do this in the Fragment, 586 // but that Fragment is re-used in other views. 587 final ActionBar actionBar = getActionBar(); 588 if (actionBar == null) return false; 589 final Tab tab = actionBar.getSelectedTab(); 590 if (tab == null) return false; 591 final int tabIndex = tab.getPosition(); 592 if (tabIndex != TAB_INDEX_CONTACTS && tabIndex != TAB_INDEX_FAVORITES) return false; 593 594 MenuInflater inflater = getMenuInflater(); 595 inflater.inflate(R.menu.list, menu); 596 return true; 597 } 598 599 @Override 600 public boolean onOptionsItemSelected(MenuItem item) { 601 // This is currently a copy of the equivalent code of PeopleActivity (with the 602 // exception of menu_add, because we do not select items in the list). 603 // Should be consolidated 604 switch (item.getItemId()) { 605 case R.id.menu_settings: { 606 final Intent intent = new Intent(this, ContactsPreferenceActivity.class); 607 startActivity(intent); 608 return true; 609 } 610 case R.id.menu_search: { 611 onSearchRequested(); 612 return true; 613 } 614 case R.id.menu_add: { 615 final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); 616 startActivity(intent); 617 return true; 618 } 619 case R.id.menu_import_export: { 620 ImportExportDialogFragment.show(getFragmentManager()); 621 return true; 622 } 623 case R.id.menu_accounts: { 624 final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS); 625 intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] { 626 ContactsContract.AUTHORITY 627 }); 628 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 629 startActivity(intent); 630 return true; 631 } 632 default: 633 return super.onOptionsItemSelected(item); 634 } 635 } 636 637 @Override 638 public void startSearch(String initialQuery, boolean selectInitialQuery, 639 Bundle appSearchData, boolean globalSearch) { 640 if (mPhoneNumberPickerFragment != null && mPhoneNumberPickerFragment.isAdded() 641 && !globalSearch) { 642 enterSearchUi(); 643 } else { 644 super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch); 645 } 646 } 647 648 /** 649 * Hides every tab and shows search UI for phone lookup. 650 */ 651 private void enterSearchUi() { 652 final ActionBar actionBar = getActionBar(); 653 654 final Tab tab = actionBar.getSelectedTab(); 655 if (tab != null) { 656 mLastManuallySelectedTab = tab.getPosition(); 657 } 658 659 // Instantiate or reset SearchView in ActionBar. 660 if (mSearchView == null) { 661 // TODO: layout is not what we want. Need "up" button instead of "close" button, etc. 662 final View searchViewLayout = 663 getLayoutInflater().inflate(R.layout.custom_action_bar, null); 664 mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view); 665 mSearchView.setQueryHint(getString(R.string.hint_findContacts)); 666 mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener); 667 mSearchView.setOnCloseListener(mPhoneSearchCloseListener); 668 mSearchView.requestFocus(); 669 actionBar.setCustomView(searchViewLayout, 670 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 671 } else { 672 mSearchView.setQuery(null, true); 673 } 674 675 actionBar.setDisplayShowCustomEnabled(true); 676 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 677 678 // Show the search fragment and hide everything else. 679 final FragmentTransaction transaction = getFragmentManager().beginTransaction(); 680 transaction.show(mPhoneNumberPickerFragment); 681 transaction.hide(mDialpadFragment); 682 transaction.hide(mCallLogFragment); 683 transaction.hide(mContactsFragment); 684 transaction.hide(mStrequentFragment); 685 transaction.commit(); 686 687 mInSearchUi = true; 688 } 689 690 /** 691 * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment 692 * should be automatically focused again. 693 */ 694 private void exitSearchUi() { 695 final ActionBar actionBar = getActionBar(); 696 697 // We want to hide SearchView and show Tabs. Also focus on previously selected one. 698 actionBar.setDisplayShowCustomEnabled(false); 699 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 700 701 // Request to update option menu. 702 invalidateOptionsMenu(); 703 704 mInSearchUi = false; 705 } 706} 707