ActionBarAdapter.java revision e0c66aff27473d0edbd95660b95f0f2a80ab63ec
108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov/* 2fcfdffb439ccf1ddef971109b82e782c47161572Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * 408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * you may not use this file except in compliance with the License. 608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * You may obtain a copy of the License at 708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * 808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * 1008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 1108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 1208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * See the License for the specific language governing permissions and 1408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov * limitations under the License. 1508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov */ 1608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 1708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovpackage com.android.contacts.activities; 1808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 1908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport com.android.contacts.R; 20b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuanimport com.android.contacts.activities.ActionBarAdapter.Listener.Action; 2108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport com.android.contacts.list.ContactsRequest; 2208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 231a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport android.app.ActionBar; 241ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuanimport android.app.ActionBar.LayoutParams; 254d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onukiimport android.app.ActionBar.Tab; 264d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onukiimport android.app.FragmentTransaction; 2708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport android.content.Context; 284d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onukiimport android.content.res.TypedArray; 2908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport android.os.Bundle; 3015ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikovimport android.text.TextUtils; 311ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuanimport android.view.LayoutInflater; 321ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuanimport android.view.View; 331a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport android.widget.SearchView; 341a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport android.widget.SearchView.OnCloseListener; 35c5792ae6760291d435e91e0fdd28ece6b3311439Adam Powellimport android.widget.SearchView.OnQueryTextListener; 3692a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov 3708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov/** 38fcfdffb439ccf1ddef971109b82e782c47161572Dmitri Plotnikov * Adapter for the action bar at the top of the Contacts activity. 3908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov */ 40495db43f0a08bd71ba28a42f89b80d38af15afecKatherine Kuanpublic class ActionBarAdapter implements OnQueryTextListener, OnCloseListener { 4108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 4208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov public interface Listener { 43b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan public enum Action { 44b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan CHANGE_SEARCH_QUERY, START_SEARCH_MODE, STOP_SEARCH_MODE 45b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan } 46b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan 47b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan void onAction(Action action); 484d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 494d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki /** 504d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * Called when the user selects a tab. The new tab can be obtained using 514d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * {@link #getCurrentTab}. 524d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki */ 534d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki void onSelectedTabChanged(); 5408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 5508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 5615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov private static final String EXTRA_KEY_SEARCH_MODE = "navBar.searchMode"; 5708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov private static final String EXTRA_KEY_QUERY = "navBar.query"; 5859dc2751d64f60f743b8a9e78186aa5b79dcaf83Isaac Katzenelson private static final String EXTRA_KEY_SELECTED_TAB = "navBar.selectedTab"; 5908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 6015ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov private boolean mSearchMode; 6108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov private String mQueryString; 6215ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov 63b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan private String mSearchLabelText; 6415ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov private SearchView mSearchView; 6592a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov 6608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov private final Context mContext; 674ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki private final boolean mAlwaysShowSearchView; 6808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 6908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov private Listener mListener; 7008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 714d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private final ActionBar mActionBar; 724d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private final MyTabListener mTabListener = new MyTabListener(); 738b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov 74e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki private boolean mShowHomeIcon; 75e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 764d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public enum TabState { 774d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki FAVORITES, ALL, GROUPS; 781ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan 794d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public static TabState fromInt(int value) { 804d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki switch (value) { 814d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki case 0: 824d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki return FAVORITES; 834d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki case 1: 844d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki return ALL; 854d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki case 2: 864d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki return GROUPS; 874d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 884d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki throw new IllegalArgumentException("Invalid value: " + value); 894d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 904d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 914d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 924d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private TabState mCurrentTab = TabState.FAVORITES; 934d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 944d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public ActionBarAdapter(Context context, Listener listener, ActionBar actionBar) { 9508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov mContext = context; 961ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan mListener = listener; 974d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar = actionBar; 98b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan mSearchLabelText = mContext.getString(R.string.search_label); 994ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mAlwaysShowSearchView = mContext.getResources().getBoolean(R.bool.always_show_search_view); 10008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 101e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki mShowHomeIcon = mContext.getResources().getBoolean(R.bool.show_home_icon); 102e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 1034ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki // Set up search view. 1044ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki View customSearchView = LayoutInflater.from(mContext).inflate(R.layout.custom_action_bar, 1054ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki null); 1064ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki int searchViewWidth = mContext.getResources().getDimensionPixelSize( 1074ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki R.dimen.search_view_width); 1084ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki if (searchViewWidth == 0) { 1094ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki searchViewWidth = LayoutParams.MATCH_PARENT; 1101173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov } 1114ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki LayoutParams layoutParams = new LayoutParams(searchViewWidth, LayoutParams.WRAP_CONTENT); 1124ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mSearchView = (SearchView) customSearchView.findViewById(R.id.search_view); 1134ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mSearchView.setQueryHint(mContext.getString(R.string.hint_findContacts)); 114c5792ae6760291d435e91e0fdd28ece6b3311439Adam Powell mSearchView.setOnQueryTextListener(this); 11515ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov mSearchView.setOnCloseListener(this); 11615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov mSearchView.setQuery(mQueryString, false); 1174ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mActionBar.setCustomView(customSearchView, layoutParams); 1184ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki 119e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki // Set up tabs 1204d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki addTab(TabState.FAVORITES, mContext.getString(R.string.contactsFavoritesLabel)); 1214d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki addTab(TabState.ALL, mContext.getString(R.string.contactsAllLabel)); 1224d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki addTab(TabState.GROUPS, mContext.getString(R.string.contactsGroupsLabel)); 1234d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1244d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1254d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public void initialize(Bundle savedState, ContactsRequest request) { 1264d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (savedState == null) { 1274d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mSearchMode = request.isSearchMode(); 1284d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mQueryString = request.getQueryString(); 1294d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } else { 1304d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mSearchMode = savedState.getBoolean(EXTRA_KEY_SEARCH_MODE); 1314d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mQueryString = savedState.getString(EXTRA_KEY_QUERY); 1324d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1334d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // Just set to the field here. The listener will be notified by update(). 1344d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mCurrentTab = TabState.fromInt(savedState.getInt(EXTRA_KEY_SELECTED_TAB)); 1354d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1364ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki update(); 1378b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov } 1388b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov 1391a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov public void setListener(Listener listener) { 1401a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov mListener = listener; 14108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 14208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 1434d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private void addTab(TabState tabState, String text) { 1444d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki final Tab tab = mActionBar.newTab(); 1454d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki tab.setTag(tabState); 1464d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki tab.setText(text); 1474d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki tab.setTabListener(mTabListener); 1484d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar.addTab(tab); 1494d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1504d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1514d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private class MyTabListener implements ActionBar.TabListener { 1524d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki /** 1534d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * If true, it won't call {@link #setCurrentTab} in {@link #onTabSelected}. 1544d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * This flag is used when we want to programmatically update the current tab without 1554d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * {@link #onTabSelected} getting called. 1564d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki */ 1574d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public boolean mIgnoreTabSelected; 1584d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1594d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } 1604d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } 1614d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1624d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { 1634d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (!mIgnoreTabSelected) { 1644d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki setCurrentTab((TabState)tab.getTag()); 1654d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1664d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1674d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1684d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1694d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki /** 1704d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki * Change the current tab, and notify the listener. 1714d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki */ 1724d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public void setCurrentTab(TabState tab) { 173250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki setCurrentTab(tab, true); 174250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki } 175250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki 176250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki /** 177250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki * Change the current tab 178250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki */ 179250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki public void setCurrentTab(TabState tab, boolean notifyListener) { 1804d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (tab == null) throw new NullPointerException(); 1814d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (tab == mCurrentTab) { 1824d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki return; 1834d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1844d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mCurrentTab = tab; 1854d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1864d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki int index = mCurrentTab.ordinal(); 1874d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if ((mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) 1884d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki && (index != mActionBar.getSelectedNavigationIndex())) { 1894d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar.setSelectedNavigationItem(index); 1904d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1914d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 192250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki if (notifyListener && mListener != null) mListener.onSelectedTabChanged(); 1934d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1944d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 1954d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki public TabState getCurrentTab() { 1964d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki return mCurrentTab; 1974d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 1984d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki 19915ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov public boolean isSearchMode() { 20015ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov return mSearchMode; 20108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 20208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 20315ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov public void setSearchMode(boolean flag) { 20415ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov if (mSearchMode != flag) { 20515ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov mSearchMode = flag; 206bee8d3bd37edf44c535c0cc401e8d03f095b8328Dmitri Plotnikov update(); 207f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan if (mSearchView == null) { 208f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan return; 209f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan } 2100b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov if (mSearchMode) { 2114ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki setFocusOnSearchView(); 212ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov } else { 213ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov mSearchView.setQuery(null, false); 2140b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov } 21508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 21608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 21708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 21808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov public String getQueryString() { 21908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov return mQueryString; 22008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 22108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 22208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov public void setQueryString(String query) { 22308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov mQueryString = query; 224f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan if (mSearchView != null) { 225f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan mSearchView.setQuery(query, false); 226f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan } 22708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 22808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 229e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki /** @return true if the "UP" icon is showing. */ 230e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki public boolean isUpShowing() { 231e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki return mSearchMode; // Only shown on the search mode. 232e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 233e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 234e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki private void updateDisplayOptions() { 235e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki // All the flags we may change in this method. 236e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki final int MASK = ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME 237e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_DISABLE_HOME 238e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki | ActionBar.DISPLAY_SHOW_CUSTOM; 239e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 240e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki // The current flags set to the action bar. (only the ones that we may change here) 241e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki final int current = mActionBar.getDisplayOptions() & MASK; 242e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 243e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki // Build the new flags... 244e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki int newFlags = 0; 245e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_SHOW_TITLE; 246e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki if (mShowHomeIcon) { 247e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_SHOW_HOME; 248e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 249e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki if (mSearchMode) { 250e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_SHOW_HOME; 251e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_HOME_AS_UP; 252e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_SHOW_CUSTOM; 253e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } else { 254e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_DISABLE_HOME; 255e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki if (mAlwaysShowSearchView) { 256e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki newFlags |= ActionBar.DISPLAY_SHOW_CUSTOM; 257e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 258e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 259e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 260e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki if (current != newFlags) { 261e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki // Pass the mask here to preserve other flags that we're not interested here. 262e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki mActionBar.setDisplayOptions(newFlags, MASK); 263e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 264e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki } 265e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki 2664d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki private void update() { 267b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan if (mSearchMode) { 2684ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki if (mAlwaysShowSearchView) { 2694ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki // Tablet -- change the app title for the search mode 2701ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan mActionBar.setTitle(mSearchLabelText); 2714ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki } else { 2724ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki // Phone -- search view gets focus 2734ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki setFocusOnSearchView(); 2741ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan } 2754d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (mActionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_STANDARD) { 2764d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 2774d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 278b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan if (mListener != null) { 279b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan mListener.onAction(Action.START_SEARCH_MODE); 280c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov } 28115ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov } else { 2824d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki if (mActionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_TABS) { 2834d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // setNavigationMode will trigger onTabSelected() with the tab which was previously 2844d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // selected. 2854d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // The issue is that when we're first switching to the tab navigation mode after 2864d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // screen orientation changes, onTabSelected() will get called with the first tab 2874d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // (i.e. favorite), which would results in mCurrentTab getting set to FAVORITES and 2884d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // we'd lose restored tab. 2894d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // So let's just disable the callback here temporarily. We'll notify the listener 2904d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki // after this anyway. 2914d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mTabListener.mIgnoreTabSelected = true; 2924d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 2934d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mActionBar.setSelectedNavigationItem(mCurrentTab.ordinal()); 2944d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mTabListener.mIgnoreTabSelected = false; 2954d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki } 296b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan mActionBar.setTitle(null); 297b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan if (mListener != null) { 298b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan mListener.onAction(Action.STOP_SEARCH_MODE); 2994d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki mListener.onSelectedTabChanged(); 300bee8d3bd37edf44c535c0cc401e8d03f095b8328Dmitri Plotnikov } 30108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 302e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki updateDisplayOptions(); 30308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 30408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 30508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov @Override 306c5792ae6760291d435e91e0fdd28ece6b3311439Adam Powell public boolean onQueryTextChange(String queryString) { 307b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan // TODO: Clean up SearchView code because it keeps setting the SearchView query, 308b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan // invoking onQueryChanged, setting up the fragment again, invalidating the options menu, 309b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan // storing the SearchView again, and etc... unless we add in the early return statements. 310b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan if (queryString.equals(mQueryString)) { 311b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan return false; 312b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan } 31308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov mQueryString = queryString; 314ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov if (!mSearchMode) { 315ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov if (!TextUtils.isEmpty(queryString)) { 316ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov setSearchMode(true); 3179806ed099226a19e92c29d9efa791cd187fd2a53Dmitri Plotnikov } 318ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov } else if (mListener != null) { 319b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan mListener.onAction(Action.CHANGE_SEARCH_QUERY); 3209806ed099226a19e92c29d9efa791cd187fd2a53Dmitri Plotnikov } 321ab4d29f6a2edbfae008dbaff35f25baad73aa0dfDmitri Plotnikov 3221a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov return true; 3231a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov } 3241a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov 3251a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov @Override 326c5792ae6760291d435e91e0fdd28ece6b3311439Adam Powell public boolean onQueryTextSubmit(String query) { 3271a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov return true; 32808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 32908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 33008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov @Override 3311a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov public boolean onClose() { 33215ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov setSearchMode(false); 33315ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov return false; 33408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov } 33508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov 33615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov public void onSaveInstanceState(Bundle outState) { 33715ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov outState.putBoolean(EXTRA_KEY_SEARCH_MODE, mSearchMode); 33815ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov outState.putString(EXTRA_KEY_QUERY, mQueryString); 3394d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki outState.putInt(EXTRA_KEY_SELECTED_TAB, mCurrentTab.ordinal()); 340fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov } 341fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov 3424ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki private void setFocusOnSearchView() { 3434ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mSearchView.requestFocus(); 3444ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki mSearchView.setIconified(false); // Workaround for the "IME not popping up" issue. 3454ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki } 34608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov} 347