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
193c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.animation.ValueAnimator;
20bf96dd1b542c7aa5bf5e97903b22dbd2cbe2a316Wenyi Wangimport android.app.ActionBar;
2120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.app.Activity;
2208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport android.content.Context;
2335d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onukiimport android.content.SharedPreferences;
243c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.content.res.TypedArray;
2508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikovimport android.os.Bundle;
2635d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onukiimport android.preference.PreferenceManager;
2723d9b6e86d2cd15347ff7be0e911ee4992704d44Wenyi Wangimport android.support.v4.content.ContextCompat;
286adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.text.Editable;
2915ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikovimport android.text.TextUtils;
306adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.text.TextWatcher;
3120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.view.Gravity;
323c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.view.LayoutInflater;
331ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuanimport android.view.View;
343c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.view.ViewGroup;
35d8a61b7296bf7388505f0211d7ef44700e766193Katherine Kuanimport android.view.inputmethod.InputMethodManager;
3620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.FrameLayout;
3720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.LinearLayout.LayoutParams;
381a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport android.widget.SearchView.OnCloseListener;
396adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.view.View.OnClickListener;
406adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.widget.EditText;
4120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.TextView;
42bf96dd1b542c7aa5bf5e97903b22dbd2cbe2a316Wenyi Wangimport android.widget.Toolbar;
4392a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov
44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ActionBarAdapter.Listener.Action;
464c3d3e24b0de8b4170106e312f6a4ac8139e1242Wenyi Wangimport com.android.contacts.common.compat.CompatUtils;
47e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.list.ContactsRequest;
48e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
4908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov/**
50fcfdffb439ccf1ddef971109b82e782c47161572Dmitri Plotnikov * Adapter for the action bar at the top of the Contacts activity.
5108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov */
526adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellpublic class ActionBarAdapter implements OnCloseListener {
5308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
5408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public interface Listener {
55311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        public abstract class Action {
56311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            public static final int CHANGE_SEARCH_QUERY = 0;
57311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            public static final int START_SEARCH_MODE = 1;
5820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            public static final int START_SELECTION_MODE = 2;
5920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            public static final int STOP_SEARCH_AND_SELECTION_MODE = 3;
60865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell            public static final int BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE = 4;
61b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan        }
62b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan
63311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        void onAction(int action);
644d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
654d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        /**
664d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         * Called when the user selects a tab.  The new tab can be obtained using
674d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         * {@link #getCurrentTab}.
684d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         */
694d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        void onSelectedTabChanged();
706adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
716adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        void onUpButtonPressed();
7208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
7308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
7415ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    private static final String EXTRA_KEY_SEARCH_MODE = "navBar.searchMode";
7508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private static final String EXTRA_KEY_QUERY = "navBar.query";
7659dc2751d64f60f743b8a9e78186aa5b79dcaf83Isaac Katzenelson    private static final String EXTRA_KEY_SELECTED_TAB = "navBar.selectedTab";
7720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private static final String EXTRA_KEY_SELECTED_MODE = "navBar.selectionMode";
7808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
7935d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    private static final String PERSISTENT_LAST_TAB = "actionBarAdapter.lastTab";
8035d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
8120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private boolean mSelectionMode;
8215ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    private boolean mSearchMode;
8308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private String mQueryString;
8415ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov
856adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private EditText mSearchView;
86ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee    private View mClearSearchView;
873c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    /** The view that represents tabs when we are in portrait mode **/
883c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private View mPortraitTabs;
893c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    /** The view that represents tabs when we are in landscape mode **/
903c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private View mLandscapeTabs;
916adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private View mSearchContainer;
9220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private View mSelectionContainer;
9392a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov
943c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private int mMaxPortraitTabHeight;
953c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private int mMaxToolbarContentInsetStart;
963c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
9720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private final Activity mActivity;
9835d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    private final SharedPreferences mPrefs;
9908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
10008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private Listener mListener;
10108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
1024d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    private final ActionBar mActionBar;
1033c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private final Toolbar mToolbar;
10420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    /**
10520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     *  Frame that contains the toolbar and draws the toolbar's background color. This is useful
10620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     *  for placing things behind the toolbar.
10720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     */
10820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private final FrameLayout mToolBarFrame;
1098b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov
110e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    private boolean mShowHomeIcon;
111e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
11252aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public interface TabState {
1133b6a6f6ac9dce6028248ed7a695ed2c76890add8Paul Sliwowski        public static int FAVORITES = 0;
11452aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        public static int ALL = 1;
11552aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann
1165f057fa8a0d1be9529024846c9e69b5764078d2cPaul Soulos        public static int COUNT = 2;
11752aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        public static int DEFAULT = ALL;
1184d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
1194d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
12052aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private int mCurrentTab = TabState.DEFAULT;
1214d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
12220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public ActionBarAdapter(Activity activity, Listener listener, ActionBar actionBar,
1233c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            View portraitTabs, View landscapeTabs, Toolbar toolbar) {
12420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mActivity = activity;
1251ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan        mListener = listener;
1264d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        mActionBar = actionBar;
12720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mPrefs = PreferenceManager.getDefaultSharedPreferences(mActivity);
1283c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mPortraitTabs = portraitTabs;
1293c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mLandscapeTabs = landscapeTabs;
1303c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar = toolbar;
13120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame = (FrameLayout) mToolbar.getParent();
1323c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mMaxToolbarContentInsetStart = mToolbar.getContentInsetStart();
13320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mShowHomeIcon = mActivity.getResources().getBoolean(R.bool.show_home_icon);
134e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
13520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        setupSearchAndSelectionViews();
13620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        setupTabs(mActivity);
1377f5220e23b37b76cf484b28c182a0c98749b59e2Maurice Chu    }
1387f5220e23b37b76cf484b28c182a0c98749b59e2Maurice Chu
1393c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void setupTabs(Context context) {
1403c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final TypedArray attributeArray = context.obtainStyledAttributes(
1413c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                new int[]{android.R.attr.actionBarSize});
1423c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mMaxPortraitTabHeight = attributeArray.getDimensionPixelSize(0, 0);
1433c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        // Hide tabs initially
1443c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        setPortraitTabHeight(0);
1454d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
146ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee
14720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void setupSearchAndSelectionViews() {
1483c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final LayoutInflater inflater = (LayoutInflater) mToolbar.getContext().getSystemService(
1493c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                Context.LAYOUT_INFLATER_SERVICE);
15020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
15120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Setup search bar
1523c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mSearchContainer = inflater.inflate(R.layout.search_bar_expanded, mToolbar,
1533c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                /* attachToRoot = */ false);
1543c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mSearchContainer.setVisibility(View.VISIBLE);
1553c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.addView(mSearchContainer);
15620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSearchContainer.setBackgroundColor(mActivity.getResources().getColor(
1576adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                R.color.searchbox_background_color));
1586adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchView = (EditText) mSearchContainer.findViewById(R.id.search_view);
15920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSearchView.setHint(mActivity.getString(R.string.hint_findContacts));
1606adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchView.addTextChangedListener(new SearchTextWatcher());
161ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee        mSearchContainer.findViewById(R.id.search_back_button).setOnClickListener(
1626adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                new OnClickListener() {
1636adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            @Override
1646adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            public void onClick(View v) {
165ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee                if (mListener != null) {
166ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee                    mListener.onUpButtonPressed();
167ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee                }
1686adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
1696adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        });
170ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee
171ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee        mClearSearchView = mSearchContainer.findViewById(R.id.search_close_button);
172ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee        mClearSearchView.setOnClickListener(
1736adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                new OnClickListener() {
1746adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            @Override
1756adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            public void onClick(View v) {
176ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee                setQueryString(null);
1776adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
1786adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        });
17920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
18020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Setup selection bar
18120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSelectionContainer = inflater.inflate(R.layout.selection_bar, mToolbar,
18220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                /* attachToRoot = */ false);
18320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Insert the selection container into mToolBarFrame behind the Toolbar, so that
18420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // the Toolbar's MenuItems can appear on top of the selection container.
18520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.addView(mSelectionContainer, 0);
18620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSelectionContainer.findViewById(R.id.selection_close).setOnClickListener(
18720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                new OnClickListener() {
18820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    @Override
18920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    public void onClick(View v) {
19020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        if (mListener != null) {
19120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                            mListener.onUpButtonPressed();
19220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        }
19320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    }
19420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                });
1956adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
1966adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
1974d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    public void initialize(Bundle savedState, ContactsRequest request) {
1984d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        if (savedState == null) {
1994d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mSearchMode = request.isSearchMode();
2004d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mQueryString = request.getQueryString();
20135d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki            mCurrentTab = loadLastTabPreference();
202d2962a3bb669a381d31a586df3b906033a8fa571Brian Attwell            mSelectionMode = false;
2034d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        } else {
2044d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mSearchMode = savedState.getBoolean(EXTRA_KEY_SEARCH_MODE);
20520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mSelectionMode = savedState.getBoolean(EXTRA_KEY_SELECTED_MODE);
2064d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mQueryString = savedState.getString(EXTRA_KEY_QUERY);
2079eb87f4e4a41fec748ce48281f85f3b3ae32fb93Wenyi Wang
2084d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            // Just set to the field here.  The listener will be notified by update().
20952aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            mCurrentTab = savedState.getInt(EXTRA_KEY_SELECTED_TAB);
2104d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        }
21126dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell        if (mCurrentTab >= TabState.COUNT || mCurrentTab < 0) {
21226dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell            // Invalid tab index was saved (b/12938207). Restore the default.
21326dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell            mCurrentTab = TabState.DEFAULT;
21426dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell        }
2153c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // Show tabs or the expanded {@link SearchView}, depending on whether or not we are in
2163c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // search mode.
2176adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        update(true /* skipAnimation */);
2183c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // Expanding the {@link SearchView} clears the query, so set the query from the
2193c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // {@link ContactsRequest} after it has been expanded, if applicable.
2203c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        if (mSearchMode && !TextUtils.isEmpty(mQueryString)) {
2213c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            setQueryString(mQueryString);
2223c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        }
2238b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov    }
2248b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov
2251a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov    public void setListener(Listener listener) {
2261a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov        mListener = listener;
22708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
22808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
2296adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private class SearchTextWatcher implements TextWatcher {
2306adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2316adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2326adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void onTextChanged(CharSequence queryString, int start, int before, int count) {
2336adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (queryString.equals(mQueryString)) {
2346adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                return;
2356adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
2366adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            mQueryString = queryString.toString();
2376adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (!mSearchMode) {
2386adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                if (!TextUtils.isEmpty(queryString)) {
2396adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    setSearchMode(true);
2406adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                }
2416adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            } else if (mListener != null) {
2426adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mListener.onAction(Action.CHANGE_SEARCH_QUERY);
2436adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
244ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee            mClearSearchView.setVisibility(
245ad6e0eea7026d82a2e27ad4a01c3f2d2e2c4360dAndrew Lee                    TextUtils.isEmpty(queryString) ? View.GONE : View.VISIBLE);
2466adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
2476adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2486adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2496adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void afterTextChanged(Editable s) {}
2506adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2516adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2526adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
2536adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
2546adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2554d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    /**
2563c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell     * Save the current tab selection, and notify the listener.
2574d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki     */
25852aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public void setCurrentTab(int tab) {
259250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki        setCurrentTab(tab, true);
260250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki    }
261250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki
262250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki    /**
2633c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell     * Save the current tab selection.
264250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki     */
26552aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public void setCurrentTab(int tab, boolean notifyListener) {
2664d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        if (tab == mCurrentTab) {
2674d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            return;
2684d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        }
2694d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        mCurrentTab = tab;
2704d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
271250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki        if (notifyListener && mListener != null) mListener.onSelectedTabChanged();
27235d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        saveLastTabPreference(mCurrentTab);
2734d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
2744d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
27552aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public int getCurrentTab() {
2764d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        return mCurrentTab;
2774d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
2784d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
2791db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki    /**
2801db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * @return Whether in search mode, i.e. if the search view is visible/expanded.
2811db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     *
2821db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * Note even if the action bar is in search mode, if the query is empty, the search fragment
2831db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * will not be in search mode.
2841db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     */
28515ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public boolean isSearchMode() {
28615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        return mSearchMode;
28708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
28808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
28920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    /**
29020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     * @return Whether in selection mode, i.e. if the selection view is visible/expanded.
29120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     */
29220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public boolean isSelectionMode() {
29320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        return mSelectionMode;
29420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
29520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
29615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public void setSearchMode(boolean flag) {
29715ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        if (mSearchMode != flag) {
29815ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov            mSearchMode = flag;
2996adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            update(false /* skipAnimation */);
300f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan            if (mSearchView == null) {
301f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan                return;
302f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan            }
3030b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov            if (mSearchMode) {
30487901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                mSearchView.setEnabled(true);
3054ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki                setFocusOnSearchView();
30687901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell            } else {
30787901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                // Disable search view, so that it doesn't keep the IME visible.
30887901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                mSearchView.setEnabled(false);
3090b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov            }
310b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            setQueryString(null);
311311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        } else if (flag) {
312311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            // Everything is already set up. Still make sure the keyboard is up
313311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            if (mSearchView != null) setFocusOnSearchView();
31408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        }
31508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
31608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
31720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public void setSelectionMode(boolean flag) {
31820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode != flag) {
31920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mSelectionMode = flag;
32020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            update(false /* skipAnimation */);
32120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
32220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
32320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
32408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public String getQueryString() {
3251db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki        return mSearchMode ? mQueryString : null;
32608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
32708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
32808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public void setQueryString(String query) {
32908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        mQueryString = query;
330f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan        if (mSearchView != null) {
3316adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            mSearchView.setText(query);
332b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            // When programmatically entering text into the search view, the most reasonable
333b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            // place for the cursor is after all the text.
334b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            mSearchView.setSelection(mSearchView.getText() == null ?
335b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell                    0 : mSearchView.getText().length());
336f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan        }
33708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
33808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
339e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    /** @return true if the "UP" icon is showing. */
340e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    public boolean isUpShowing() {
341e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        return mSearchMode; // Only shown on the search mode.
342e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    }
343e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
3443c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void updateDisplayOptionsInner() {
345e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // All the flags we may change in this method.
346e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        final int MASK = ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME
34720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                | ActionBar.DISPLAY_HOME_AS_UP;
348e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
349e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // The current flags set to the action bar.  (only the ones that we may change here)
350e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        final int current = mActionBar.getDisplayOptions() & MASK;
351e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
35220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSearchOrSelectionMode = mSearchMode || mSelectionMode;
35320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
354e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // Build the new flags...
355e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        int newFlags = 0;
35620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mShowHomeIcon && !isSearchOrSelectionMode) {
357e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            newFlags |= ActionBar.DISPLAY_SHOW_HOME;
358e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
359865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        if (mSearchMode && !mSelectionMode) {
36020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // The search container is placed inside the toolbar. So we need to disable the
36120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // Toolbar's content inset in order to allow the search container to be the width of
36220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // the window.
3633c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.setContentInsetsRelative(0, mToolbar.getContentInsetEnd());
36420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
36520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (!isSearchOrSelectionMode) {
3666adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            newFlags |= ActionBar.DISPLAY_SHOW_TITLE;
3673c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.setContentInsetsRelative(mMaxToolbarContentInsetStart,
3683c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                    mToolbar.getContentInsetEnd());
369e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
370b0d3c7609a21d7432bcac0cf97411d1ff64851baBrian Attwell
37120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode) {
37220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // Minimize the horizontal width of the Toolbar since the selection container is placed
37320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // behind the toolbar and its left hand side needs to be clickable.
37420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mToolbar.getLayoutParams();
37520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.width = LayoutParams.WRAP_CONTENT;
37620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.gravity = Gravity.END;
37720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.setLayoutParams(params);
37820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
37920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mToolbar.getLayoutParams();
38020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.width = LayoutParams.MATCH_PARENT;
38120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.gravity = Gravity.END;
38220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.setLayoutParams(params);
38320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
3843c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
385e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        if (current != newFlags) {
386e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            // Pass the mask here to preserve other flags that we're not interested here.
387e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            mActionBar.setDisplayOptions(newFlags, MASK);
388e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
389e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    }
390e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
3916adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private void update(boolean skipAnimation) {
39220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        updateStatusBarColor();
39320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
39420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSelectionModeChanging
39520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                = (mSelectionContainer.getParent() == null) == mSelectionMode;
396865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        final boolean isSwitchingFromSearchToSelection =
397865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                mSearchMode && isSelectionModeChanging || mSearchMode && mSelectionMode;
39820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSearchModeChanging
3993c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                = (mSearchContainer.getParent() == null) == mSearchMode;
40020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isTabHeightChanging = isSearchModeChanging || isSelectionModeChanging;
40120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
40220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // When skipAnimation=true, it is possible that we will switch from search mode
40320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // to selection mode directly. So we need to remove the undesired container in addition
40420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // to adding the desired container.
405865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        if (skipAnimation || isSwitchingFromSearchToSelection) {
406865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell            if (isTabHeightChanging || isSwitchingFromSearchToSelection) {
40720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mToolbar.removeView(mLandscapeTabs);
408865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                mToolbar.removeView(mSearchContainer);
409865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                mToolBarFrame.removeView(mSelectionContainer);
410865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                if (mSelectionMode) {
41120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    setPortraitTabHeight(0);
41220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    addSelectionContainer();
413865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                } else if (mSearchMode) {
414865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                    setPortraitTabHeight(0);
415865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                    addSearchContainer();
41620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                } else {
41720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    setPortraitTabHeight(mMaxPortraitTabHeight);
41820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    addLandscapeViewPagerTabs();
41920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                }
42020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
42120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
42220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            return;
42320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
42420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
42520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Handle a switch to/from selection mode, due to UI interaction.
42620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (isSelectionModeChanging) {
42720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.removeView(mLandscapeTabs);
42820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSelectionMode) {
42920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                addSelectionContainer();
43020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.setAlpha(0);
43120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.animate().alpha(1);
43220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                animateTabHeightChange(mMaxPortraitTabHeight, 0);
43320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
43420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            } else {
435865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                if (mListener != null) {
436865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                    mListener.onAction(Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE);
437865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell                }
43820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.setAlpha(1);
43920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                animateTabHeightChange(0, mMaxPortraitTabHeight);
44020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.animate().alpha(0).withEndAction(new Runnable() {
44120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    @Override
44220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    public void run() {
44320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        updateDisplayOptions(isSearchModeChanging);
44420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        addLandscapeViewPagerTabs();
44520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        mToolBarFrame.removeView(mSelectionContainer);
44620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    }
44720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                });
44820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
44920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
45020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
45120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Handle a switch to/from search mode, due to UI interaction.
45220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (isSearchModeChanging) {
4538d71f11c70c974518f3482c46a10a5601628a029Brian Attwell            mToolbar.removeView(mLandscapeTabs);
4546adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (mSearchMode) {
4553c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                addSearchContainer();
4566adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.setAlpha(0);
4576adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.animate().alpha(1);
4583c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                animateTabHeightChange(mMaxPortraitTabHeight, 0);
45920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
4606adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            } else {
4616adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.setAlpha(1);
4623c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                animateTabHeightChange(0, mMaxPortraitTabHeight);
4636adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.animate().alpha(0).withEndAction(new Runnable() {
4646adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    @Override
4656adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    public void run() {
46620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        updateDisplayOptions(isSearchModeChanging);
4673c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                        addLandscapeViewPagerTabs();
4683c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                        mToolbar.removeView(mSearchContainer);
4696adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    }
4706adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                });
4716adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
4726adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
47320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
47420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
47520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public void setSelectionCount(int selectionCount) {
47620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        TextView textView = (TextView) mSelectionContainer.findViewById(R.id.selection_count_text);
47720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (selectionCount == 0) {
47820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            textView.setVisibility(View.GONE);
47920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
48020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            textView.setVisibility(View.VISIBLE);
48120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
48220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        textView.setText(String.valueOf(selectionCount));
48320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
48420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
48520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void updateStatusBarColor() {
4864c3d3e24b0de8b4170106e312f6a4ac8139e1242Wenyi Wang        if (!CompatUtils.isLollipopCompatible()) {
4874c3d3e24b0de8b4170106e312f6a4ac8139e1242Wenyi Wang            return; // we can't change the status bar color prior to Lollipop
4884c3d3e24b0de8b4170106e312f6a4ac8139e1242Wenyi Wang        }
48920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode) {
49056dfa580b5497f25169a4c875800ffff95cd31cdWenyi Wang            final int cabStatusBarColor = mActivity.getResources().getColor(
49120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    R.color.contextual_selection_bar_status_bar_color);
49220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mActivity.getWindow().setStatusBarColor(cabStatusBarColor);
49320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
49423d9b6e86d2cd15347ff7be0e911ee4992704d44Wenyi Wang            final int normalStatusBarColor = ContextCompat.getColor(
49523d9b6e86d2cd15347ff7be0e911ee4992704d44Wenyi Wang                    mActivity, R.color.primary_color_dark);
49620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mActivity.getWindow().setStatusBarColor(normalStatusBarColor);
4976adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
4986adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
4996adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
5003c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void addLandscapeViewPagerTabs() {
5013c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mLandscapeTabs != null) {
5023c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.removeView(mLandscapeTabs);
5033c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.addView(mLandscapeTabs);
5043c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
5053c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
5063c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
5073c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void addSearchContainer() {
5083c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.removeView(mSearchContainer);
5093c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.addView(mSearchContainer);
510865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        mSearchContainer.setAlpha(1);
5113c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
5123c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
51320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void addSelectionContainer() {
51420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.removeView(mSelectionContainer);
51520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.addView(mSelectionContainer, 0);
516865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        mSelectionContainer.setAlpha(1);
51720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
51820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
51920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void updateDisplayOptions(boolean isSearchModeChanging) {
520865847b1f567cb28664a57ac9cac05c3f2a8de32Brian Attwell        if (mSearchMode && !mSelectionMode) {
5215267367e202dcb39ef0fe912a7be9209548ec436Makoto Onuki            setFocusOnSearchView();
522d8a61b7296bf7388505f0211d7ef44700e766193Katherine Kuan            // Since we have the {@link SearchView} in a custom action bar, we must manually handle
5233c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            // expanding the {@link SearchView} when a search is initiated. Note that a side effect
5243c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            // of this method is that the {@link SearchView} query text is set to empty string.
52520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (isSearchModeChanging) {
5266adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                final CharSequence queryText = mSearchView.getText();
5278d5eec3c552c2ac23bc4d3324063627d31582615Yorke Lee                if (!TextUtils.isEmpty(queryText)) {
5286adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    mSearchView.setText(queryText);
5298d5eec3c552c2ac23bc4d3324063627d31582615Yorke Lee                }
530b0d82d2703d66b3bd4fe8dc4208cdf6a09f2f4afDaniel Lehmann            }
53120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
53220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mListener != null) {
53320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSearchMode) {
534b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan                mListener.onAction(Action.START_SEARCH_MODE);
535c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov            }
53620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSelectionMode) {
53720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mListener.onAction(Action.START_SELECTION_MODE);
53820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
53920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (!mSearchMode && !mSelectionMode) {
54020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mListener.onAction(Action.STOP_SEARCH_AND_SELECTION_MODE);
5414d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki                mListener.onSelectedTabChanged();
542bee8d3bd37edf44c535c0cc401e8d03f095b8328Dmitri Plotnikov            }
54308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        }
5443c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        updateDisplayOptionsInner();
54508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
54608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
54708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    @Override
5481a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov    public boolean onClose() {
54915ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        setSearchMode(false);
55015ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        return false;
55108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
55208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
55315ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public void onSaveInstanceState(Bundle outState) {
55415ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        outState.putBoolean(EXTRA_KEY_SEARCH_MODE, mSearchMode);
55520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        outState.putBoolean(EXTRA_KEY_SELECTED_MODE, mSelectionMode);
55615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        outState.putString(EXTRA_KEY_QUERY, mQueryString);
55752aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        outState.putInt(EXTRA_KEY_SELECTED_TAB, mCurrentTab);
558fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov    }
559fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov
56009d66a382d1f94618b52fec11ba54d9243a95a18Daniel Lehmann    public void setFocusOnSearchView() {
5614ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki        mSearchView.requestFocus();
5626adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        showInputMethod(mSearchView); // Workaround for the "IME not popping up" issue.
5636adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
5646adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
5656adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private void showInputMethod(View view) {
56620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
5676adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                Context.INPUT_METHOD_SERVICE);
5686adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        if (imm != null) {
5696adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            imm.showSoftInput(view, 0);
5706adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
5714ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki    }
57235d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
57352aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private void saveLastTabPreference(int tab) {
57452aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        mPrefs.edit().putInt(PERSISTENT_LAST_TAB, tab).apply();
57535d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    }
57635d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
57752aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private int loadLastTabPreference() {
57835d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        try {
57952aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            return mPrefs.getInt(PERSISTENT_LAST_TAB, TabState.DEFAULT);
58035d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        } catch (IllegalArgumentException e) {
58135d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki            // Preference is corrupt?
58252aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            return TabState.DEFAULT;
58335d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        }
58435d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    }
5853c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
5863c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void animateTabHeightChange(int start, int end) {
5873c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mPortraitTabs == null) {
5883c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            return;
5893c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
5903c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final ValueAnimator animator = ValueAnimator.ofInt(start, end);
5913c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
5923c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            @Override
5933c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            public void onAnimationUpdate(ValueAnimator valueAnimator) {
5943c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                int value = (Integer) valueAnimator.getAnimatedValue();
5953c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                setPortraitTabHeight(value);
5963c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            }
5973c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        });
5983c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        animator.setDuration(100).start();
5993c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
6003c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
6013c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void setPortraitTabHeight(int height) {
6023c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mPortraitTabs == null) {
6033c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            return;
6043c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
6053c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        ViewGroup.LayoutParams layoutParams = mPortraitTabs.getLayoutParams();
6063c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        layoutParams.height = height;
6073c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mPortraitTabs.setLayoutParams(layoutParams);
6083c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
60908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov}
610