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