ActionBarAdapter.java revision d2962a3bb669a381d31a586df3b906033a8fa571
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;
201a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport 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;
276adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.text.Editable;
2815ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikovimport android.text.TextUtils;
296adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.text.TextWatcher;
3020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.view.Gravity;
313c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.view.LayoutInflater;
321ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuanimport android.view.View;
333c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.view.ViewGroup;
34d8a61b7296bf7388505f0211d7ef44700e766193Katherine Kuanimport android.view.inputmethod.InputMethodManager;
3520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.FrameLayout;
3620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.LinearLayout.LayoutParams;
371a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikovimport android.widget.SearchView.OnCloseListener;
386adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.view.View.OnClickListener;
396adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellimport android.widget.EditText;
4020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwellimport android.widget.TextView;
413c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwellimport android.widget.Toolbar;
4292a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov
43e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ActionBarAdapter.Listener.Action;
45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.list.ContactsRequest;
46e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
4708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov/**
48fcfdffb439ccf1ddef971109b82e782c47161572Dmitri Plotnikov * Adapter for the action bar at the top of the Contacts activity.
4908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov */
506adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwellpublic class ActionBarAdapter implements OnCloseListener {
5108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
5208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public interface Listener {
53311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        public abstract class Action {
54311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            public static final int CHANGE_SEARCH_QUERY = 0;
55311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            public static final int START_SEARCH_MODE = 1;
5620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            public static final int START_SELECTION_MODE = 2;
5720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            public static final int STOP_SEARCH_AND_SELECTION_MODE = 3;
58b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan        }
59b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan
60311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        void onAction(int action);
614d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
624d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        /**
634d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         * Called when the user selects a tab.  The new tab can be obtained using
644d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         * {@link #getCurrentTab}.
654d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki         */
664d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        void onSelectedTabChanged();
676adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
686adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        void onUpButtonPressed();
6908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
7008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
7115ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    private static final String EXTRA_KEY_SEARCH_MODE = "navBar.searchMode";
7208e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private static final String EXTRA_KEY_QUERY = "navBar.query";
7359dc2751d64f60f743b8a9e78186aa5b79dcaf83Isaac Katzenelson    private static final String EXTRA_KEY_SELECTED_TAB = "navBar.selectedTab";
7420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private static final String EXTRA_KEY_SELECTED_MODE = "navBar.selectionMode";
7508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
7635d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    private static final String PERSISTENT_LAST_TAB = "actionBarAdapter.lastTab";
7735d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
7820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private boolean mSelectionMode;
7915ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    private boolean mSearchMode;
8008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private String mQueryString;
8115ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov
826adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private EditText mSearchView;
833c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    /** The view that represents tabs when we are in portrait mode **/
843c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private View mPortraitTabs;
853c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    /** The view that represents tabs when we are in landscape mode **/
863c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private View mLandscapeTabs;
876adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private View mSearchContainer;
8820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private View mSelectionContainer;
8992a6fdf1b07b8f1447560174e24455fd46aee7cdDmitri Plotnikov
903c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private int mMaxPortraitTabHeight;
913c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private int mMaxToolbarContentInsetStart;
923c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
9320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private final Activity mActivity;
9435d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    private final SharedPreferences mPrefs;
9508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
9608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    private Listener mListener;
9708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
984d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    private final ActionBar mActionBar;
993c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private final Toolbar mToolbar;
10020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    /**
10120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     *  Frame that contains the toolbar and draws the toolbar's background color. This is useful
10220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     *  for placing things behind the toolbar.
10320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     */
10420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private final FrameLayout mToolBarFrame;
1058b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov
106e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    private boolean mShowHomeIcon;
107e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
10852aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public interface TabState {
1093b6a6f6ac9dce6028248ed7a695ed2c76890add8Paul Sliwowski        public static int FAVORITES = 0;
11052aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        public static int ALL = 1;
11152aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann
1125f057fa8a0d1be9529024846c9e69b5764078d2cPaul Soulos        public static int COUNT = 2;
11352aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        public static int DEFAULT = ALL;
1144d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
1154d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
11652aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private int mCurrentTab = TabState.DEFAULT;
1174d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
11820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public ActionBarAdapter(Activity activity, Listener listener, ActionBar actionBar,
1193c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            View portraitTabs, View landscapeTabs, Toolbar toolbar) {
12020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mActivity = activity;
1211ee9df6facd2340416d6a33aeb739707643d2fc3Katherine Kuan        mListener = listener;
1224d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        mActionBar = actionBar;
12320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mPrefs = PreferenceManager.getDefaultSharedPreferences(mActivity);
1243c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mPortraitTabs = portraitTabs;
1253c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mLandscapeTabs = landscapeTabs;
1263c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar = toolbar;
12720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame = (FrameLayout) mToolbar.getParent();
1283c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mMaxToolbarContentInsetStart = mToolbar.getContentInsetStart();
12920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mShowHomeIcon = mActivity.getResources().getBoolean(R.bool.show_home_icon);
130e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
13120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        setupSearchAndSelectionViews();
13220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        setupTabs(mActivity);
1337f5220e23b37b76cf484b28c182a0c98749b59e2Maurice Chu    }
1347f5220e23b37b76cf484b28c182a0c98749b59e2Maurice Chu
1353c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void setupTabs(Context context) {
1363c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final TypedArray attributeArray = context.obtainStyledAttributes(
1373c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                new int[]{android.R.attr.actionBarSize});
1383c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mMaxPortraitTabHeight = attributeArray.getDimensionPixelSize(0, 0);
1393c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        // Hide tabs initially
1403c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        setPortraitTabHeight(0);
1414d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
14220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void setupSearchAndSelectionViews() {
1433c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final LayoutInflater inflater = (LayoutInflater) mToolbar.getContext().getSystemService(
1443c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                Context.LAYOUT_INFLATER_SERVICE);
14520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
14620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Setup search bar
1473c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mSearchContainer = inflater.inflate(R.layout.search_bar_expanded, mToolbar,
1483c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                /* attachToRoot = */ false);
1493c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mSearchContainer.setVisibility(View.VISIBLE);
1503c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.addView(mSearchContainer);
15120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSearchContainer.setBackgroundColor(mActivity.getResources().getColor(
1526adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                R.color.searchbox_background_color));
1536adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchView = (EditText) mSearchContainer.findViewById(R.id.search_view);
15420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSearchView.setHint(mActivity.getString(R.string.hint_findContacts));
1556adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchView.addTextChangedListener(new SearchTextWatcher());
1566adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchContainer.findViewById(R.id.search_close_button).setOnClickListener(
1576adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                new OnClickListener() {
1586adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            @Override
1596adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            public void onClick(View v) {
160b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell                setQueryString(null);
1616adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
1626adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        });
1636adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        mSearchContainer.findViewById(R.id.search_back_button).setOnClickListener(
1646adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                new OnClickListener() {
1656adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            @Override
1666adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            public void onClick(View v) {
1676adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                if (mListener != null) {
1686adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    mListener.onUpButtonPressed();
1696adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                }
1706adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
1716adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        });
17220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
17320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Setup selection bar
17420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSelectionContainer = inflater.inflate(R.layout.selection_bar, mToolbar,
17520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                /* attachToRoot = */ false);
17620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Insert the selection container into mToolBarFrame behind the Toolbar, so that
17720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // the Toolbar's MenuItems can appear on top of the selection container.
17820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.addView(mSelectionContainer, 0);
17920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mSelectionContainer.findViewById(R.id.selection_close).setOnClickListener(
18020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                new OnClickListener() {
18120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    @Override
18220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    public void onClick(View v) {
18320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        if (mListener != null) {
18420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                            mListener.onUpButtonPressed();
18520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        }
18620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    }
18720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                });
1886adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
1896adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
1904d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    public void initialize(Bundle savedState, ContactsRequest request) {
1914d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        if (savedState == null) {
1924d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mSearchMode = request.isSearchMode();
1934d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mQueryString = request.getQueryString();
19435d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki            mCurrentTab = loadLastTabPreference();
195d2962a3bb669a381d31a586df3b906033a8fa571Brian Attwell            mSelectionMode = false;
1964d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        } else {
1974d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mSearchMode = savedState.getBoolean(EXTRA_KEY_SEARCH_MODE);
19820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mSelectionMode = savedState.getBoolean(EXTRA_KEY_SELECTED_MODE);
1994d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            mQueryString = savedState.getString(EXTRA_KEY_QUERY);
2004d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
2014d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            // Just set to the field here.  The listener will be notified by update().
20252aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            mCurrentTab = savedState.getInt(EXTRA_KEY_SELECTED_TAB);
2034d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        }
20426dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell        if (mCurrentTab >= TabState.COUNT || mCurrentTab < 0) {
20526dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell            // Invalid tab index was saved (b/12938207). Restore the default.
20626dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell            mCurrentTab = TabState.DEFAULT;
20726dc5592145eeddcd435daf2dae29d8e483f1b7bBrian Attwell        }
2083c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // Show tabs or the expanded {@link SearchView}, depending on whether or not we are in
2093c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // search mode.
2106adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        update(true /* skipAnimation */);
2113c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // Expanding the {@link SearchView} clears the query, so set the query from the
2123c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        // {@link ContactsRequest} after it has been expanded, if applicable.
2133c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        if (mSearchMode && !TextUtils.isEmpty(mQueryString)) {
2143c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            setQueryString(mQueryString);
2153c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan        }
2168b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov    }
2178b8264620f9362e089322d1e3a7cc5620900e6f9Dmitri Plotnikov
2181a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov    public void setListener(Listener listener) {
2191a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov        mListener = listener;
22008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
22108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
2226adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private class SearchTextWatcher implements TextWatcher {
2236adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2246adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2256adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void onTextChanged(CharSequence queryString, int start, int before, int count) {
2266adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (queryString.equals(mQueryString)) {
2276adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                return;
2286adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
2296adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            mQueryString = queryString.toString();
2306adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (!mSearchMode) {
2316adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                if (!TextUtils.isEmpty(queryString)) {
2326adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    setSearchMode(true);
2336adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                }
2346adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            } else if (mListener != null) {
2356adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mListener.onAction(Action.CHANGE_SEARCH_QUERY);
2366adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
2376adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
2386adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2396adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2406adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void afterTextChanged(Editable s) {}
2416adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2426adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        @Override
2436adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
2446adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
2456adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
2464d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    /**
2473c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell     * Save the current tab selection, and notify the listener.
2484d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki     */
24952aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public void setCurrentTab(int tab) {
250250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki        setCurrentTab(tab, true);
251250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki    }
252250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki
253250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki    /**
2543c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell     * Save the current tab selection.
255250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki     */
25652aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public void setCurrentTab(int tab, boolean notifyListener) {
2574d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        if (tab == mCurrentTab) {
2584d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki            return;
2594d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        }
2604d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        mCurrentTab = tab;
2614d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
262250ce43794cdf6820f7a13ef0195a566bd0c8c64Makoto Onuki        if (notifyListener && mListener != null) mListener.onSelectedTabChanged();
26335d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        saveLastTabPreference(mCurrentTab);
2644d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
2654d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
26652aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    public int getCurrentTab() {
2674d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki        return mCurrentTab;
2684d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki    }
2694d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki
2701db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki    /**
2711db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * @return Whether in search mode, i.e. if the search view is visible/expanded.
2721db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     *
2731db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * Note even if the action bar is in search mode, if the query is empty, the search fragment
2741db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     * will not be in search mode.
2751db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki     */
27615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public boolean isSearchMode() {
27715ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        return mSearchMode;
27808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
27908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
28020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    /**
28120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     * @return Whether in selection mode, i.e. if the selection view is visible/expanded.
28220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell     */
28320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public boolean isSelectionMode() {
28420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        return mSelectionMode;
28520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
28620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
28715ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public void setSearchMode(boolean flag) {
28815ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        if (mSearchMode != flag) {
28915ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov            mSearchMode = flag;
2906adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            update(false /* skipAnimation */);
291f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan            if (mSearchView == null) {
292f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan                return;
293f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan            }
2940b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov            if (mSearchMode) {
29587901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                mSearchView.setEnabled(true);
2964ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki                setFocusOnSearchView();
29787901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell            } else {
29887901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                // Disable search view, so that it doesn't keep the IME visible.
29987901e0e2896ffc2a03f519bcc86e7cb88098fa1Brian Attwell                mSearchView.setEnabled(false);
3000b51a8d4539cc516dc2c02948335347d1df8769bDmitri Plotnikov            }
301b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            setQueryString(null);
302311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann        } else if (flag) {
303311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            // Everything is already set up. Still make sure the keyboard is up
304311882ab2fc1e9c8264f5892a6d50722b834e348Daniel Lehmann            if (mSearchView != null) setFocusOnSearchView();
30508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        }
30608e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
30708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
30820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public void setSelectionMode(boolean flag) {
30920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode != flag) {
31020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mSelectionMode = flag;
31120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            update(false /* skipAnimation */);
31220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
31320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
31420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
31508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public String getQueryString() {
3161db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki        return mSearchMode ? mQueryString : null;
31708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
31808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
31908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    public void setQueryString(String query) {
32008e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        mQueryString = query;
321f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan        if (mSearchView != null) {
3226adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            mSearchView.setText(query);
323b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            // When programmatically entering text into the search view, the most reasonable
324b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            // place for the cursor is after all the text.
325b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell            mSearchView.setSelection(mSearchView.getText() == null ?
326b3944dcec1fb1299d8bedeef251adb0a413fba52Brian Attwell                    0 : mSearchView.getText().length());
327f3f933a798c9cfffb1c1c0cc770187b5b0b763ebKatherine Kuan        }
32808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
32908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
330e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    /** @return true if the "UP" icon is showing. */
331e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    public boolean isUpShowing() {
332e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        return mSearchMode; // Only shown on the search mode.
333e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    }
334e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
3353c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void updateDisplayOptionsInner() {
336e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // All the flags we may change in this method.
337e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        final int MASK = ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME
33820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                | ActionBar.DISPLAY_HOME_AS_UP;
339e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
340e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // The current flags set to the action bar.  (only the ones that we may change here)
341e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        final int current = mActionBar.getDisplayOptions() & MASK;
342e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
34320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSearchOrSelectionMode = mSearchMode || mSelectionMode;
34420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
345e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        // Build the new flags...
346e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        int newFlags = 0;
34720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mShowHomeIcon && !isSearchOrSelectionMode) {
348e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            newFlags |= ActionBar.DISPLAY_SHOW_HOME;
349e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
350e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        if (mSearchMode) {
35120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // The search container is placed inside the toolbar. So we need to disable the
35220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // Toolbar's content inset in order to allow the search container to be the width of
35320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // the window.
3543c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.setContentInsetsRelative(0, mToolbar.getContentInsetEnd());
35520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
35620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (!isSearchOrSelectionMode) {
3576adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            newFlags |= ActionBar.DISPLAY_SHOW_TITLE;
3583c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.setContentInsetsRelative(mMaxToolbarContentInsetStart,
3593c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                    mToolbar.getContentInsetEnd());
360e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
361b0d3c7609a21d7432bcac0cf97411d1ff64851baBrian Attwell
36220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode) {
36320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // Minimize the horizontal width of the Toolbar since the selection container is placed
36420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            // behind the toolbar and its left hand side needs to be clickable.
36520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mToolbar.getLayoutParams();
36620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.width = LayoutParams.WRAP_CONTENT;
36720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.gravity = Gravity.END;
36820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.setLayoutParams(params);
36920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
37020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mToolbar.getLayoutParams();
37120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.width = LayoutParams.MATCH_PARENT;
37220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            params.gravity = Gravity.END;
37320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.setLayoutParams(params);
37420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
3753c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
376e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        if (current != newFlags) {
377e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            // Pass the mask here to preserve other flags that we're not interested here.
378e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki            mActionBar.setDisplayOptions(newFlags, MASK);
379e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki        }
380e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki    }
381e0c66aff27473d0edbd95660b95f0f2a80ab63ecMakoto Onuki
3826adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private void update(boolean skipAnimation) {
38320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        updateStatusBarColor();
38420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
38520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSelectionModeChanging
38620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                = (mSelectionContainer.getParent() == null) == mSelectionMode;
38720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isSearchModeChanging
3883c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                = (mSearchContainer.getParent() == null) == mSearchMode;
38920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final boolean isTabHeightChanging = isSearchModeChanging || isSelectionModeChanging;
39020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
39120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // When skipAnimation=true, it is possible that we will switch from search mode
39220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // to selection mode directly. So we need to remove the undesired container in addition
39320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // to adding the desired container.
39420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (skipAnimation) {
39520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (isTabHeightChanging) {
39620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mToolbar.removeView(mLandscapeTabs);
39720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                if (mSearchMode) {
39820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    setPortraitTabHeight(0);
39920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    mToolBarFrame.removeView(mSelectionContainer);
40020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    addSearchContainer();
40120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                } else if (mSelectionMode) {
40220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    setPortraitTabHeight(0);
40320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    mToolbar.removeView(mSearchContainer);
40420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    addSelectionContainer();
40520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                } else {
40620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    setPortraitTabHeight(mMaxPortraitTabHeight);
40720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    mToolbar.removeView(mSearchContainer);
40820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    mToolBarFrame.removeView(mSelectionContainer);
40920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    addLandscapeViewPagerTabs();
41020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                }
41120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
41220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
41320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            return;
41420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
41520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
41620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Handle a switch to/from selection mode, due to UI interaction.
41720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (isSelectionModeChanging) {
41820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mToolbar.removeView(mLandscapeTabs);
41920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSelectionMode) {
42020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                addSelectionContainer();
42120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.setAlpha(0);
42220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.animate().alpha(1);
42320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                animateTabHeightChange(mMaxPortraitTabHeight, 0);
42420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
42520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            } else {
42620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.setAlpha(1);
42720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                animateTabHeightChange(0, mMaxPortraitTabHeight);
42820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mSelectionContainer.animate().alpha(0).withEndAction(new Runnable() {
42920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    @Override
43020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    public void run() {
43120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        updateDisplayOptions(isSearchModeChanging);
43220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        addLandscapeViewPagerTabs();
43320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        mToolBarFrame.removeView(mSelectionContainer);
43420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    }
43520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                });
43620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
43720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
43820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
43920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        // Handle a switch to/from search mode, due to UI interaction.
44020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (isSearchModeChanging) {
4418d71f11c70c974518f3482c46a10a5601628a029Brian Attwell            mToolbar.removeView(mLandscapeTabs);
4426adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            if (mSearchMode) {
4433c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                addSearchContainer();
4446adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.setAlpha(0);
4456adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.animate().alpha(1);
4463c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                animateTabHeightChange(mMaxPortraitTabHeight, 0);
44720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                updateDisplayOptions(isSearchModeChanging);
4486adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            } else {
4496adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.setAlpha(1);
4503c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                animateTabHeightChange(0, mMaxPortraitTabHeight);
4516adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                mSearchContainer.animate().alpha(0).withEndAction(new Runnable() {
4526adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    @Override
4536adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    public void run() {
45420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                        updateDisplayOptions(isSearchModeChanging);
4553c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                        addLandscapeViewPagerTabs();
4563c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                        mToolbar.removeView(mSearchContainer);
4576adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    }
4586adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                });
4596adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            }
4606adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
46120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
46220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
46320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    public void setSelectionCount(int selectionCount) {
46420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        TextView textView = (TextView) mSelectionContainer.findViewById(R.id.selection_count_text);
46520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (selectionCount == 0) {
46620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            textView.setVisibility(View.GONE);
46720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
46820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            textView.setVisibility(View.VISIBLE);
46920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
47020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        textView.setText(String.valueOf(selectionCount));
47120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
47220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
47320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void updateStatusBarColor() {
47420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mSelectionMode) {
47520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            int cabStatusBarColor = mActivity.getResources().getColor(
47620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                    R.color.contextual_selection_bar_status_bar_color);
47720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mActivity.getWindow().setStatusBarColor(cabStatusBarColor);
47820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        } else {
47920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            int normalStatusBarColor = mActivity.getColor(R.color.primary_color_dark);
48020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            mActivity.getWindow().setStatusBarColor(normalStatusBarColor);
4816adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
4826adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
4836adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
4843c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void addLandscapeViewPagerTabs() {
4853c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mLandscapeTabs != null) {
4863c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.removeView(mLandscapeTabs);
4873c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            mToolbar.addView(mLandscapeTabs);
4883c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
4893c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
4903c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
4913c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void addSearchContainer() {
4923c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.removeView(mSearchContainer);
4933c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mToolbar.addView(mSearchContainer);
4943c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
4953c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
49620510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void addSelectionContainer() {
49720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.removeView(mSelectionContainer);
49820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        mToolBarFrame.addView(mSelectionContainer, 0);
49920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    }
50020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell
50120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell    private void updateDisplayOptions(boolean isSearchModeChanging) {
502b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan        if (mSearchMode) {
5035267367e202dcb39ef0fe912a7be9209548ec436Makoto Onuki            setFocusOnSearchView();
504d8a61b7296bf7388505f0211d7ef44700e766193Katherine Kuan            // Since we have the {@link SearchView} in a custom action bar, we must manually handle
5053c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            // expanding the {@link SearchView} when a search is initiated. Note that a side effect
5063c877e33cb7fecc7a63af1cf3c25061d53811bf6Katherine Kuan            // of this method is that the {@link SearchView} query text is set to empty string.
50720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (isSearchModeChanging) {
5086adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                final CharSequence queryText = mSearchView.getText();
5098d5eec3c552c2ac23bc4d3324063627d31582615Yorke Lee                if (!TextUtils.isEmpty(queryText)) {
5106adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                    mSearchView.setText(queryText);
5118d5eec3c552c2ac23bc4d3324063627d31582615Yorke Lee                }
512b0d82d2703d66b3bd4fe8dc4208cdf6a09f2f4afDaniel Lehmann            }
51320510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        }
51420510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        if (mListener != null) {
51520510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSearchMode) {
516b5760b94bbf56ce348876ec36f4669d20a1530f5Katherine Kuan                mListener.onAction(Action.START_SEARCH_MODE);
517c9916d303cc48b4a4ff94ef9c56d7ca5da72c4deDmitri Plotnikov            }
51820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (mSelectionMode) {
51920510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mListener.onAction(Action.START_SELECTION_MODE);
52020510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            }
52120510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell            if (!mSearchMode && !mSelectionMode) {
52220510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell                mListener.onAction(Action.STOP_SEARCH_AND_SELECTION_MODE);
5234d788fc27ac855bd6e0cec17dff39a18564f0089Makoto Onuki                mListener.onSelectedTabChanged();
524bee8d3bd37edf44c535c0cc401e8d03f095b8328Dmitri Plotnikov            }
52508e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov        }
5263c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        updateDisplayOptionsInner();
52708e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
52808e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
52908e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    @Override
5301a59cffd839069ce91a9febb8a136442340ab4c8Dmitri Plotnikov    public boolean onClose() {
53115ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        setSearchMode(false);
53215ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        return false;
53308e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov    }
53408e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov
53515ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov    public void onSaveInstanceState(Bundle outState) {
53615ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        outState.putBoolean(EXTRA_KEY_SEARCH_MODE, mSearchMode);
53720510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        outState.putBoolean(EXTRA_KEY_SELECTED_MODE, mSelectionMode);
53815ccbb4d22fd65165cacb7970cbe61de1aa9aac4Dmitri Plotnikov        outState.putString(EXTRA_KEY_QUERY, mQueryString);
53952aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        outState.putInt(EXTRA_KEY_SELECTED_TAB, mCurrentTab);
540fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov    }
541fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov
54209d66a382d1f94618b52fec11ba54d9243a95a18Daniel Lehmann    public void setFocusOnSearchView() {
5434ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki        mSearchView.requestFocus();
5446adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        showInputMethod(mSearchView); // Workaround for the "IME not popping up" issue.
5456adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    }
5466adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell
5476adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell    private void showInputMethod(View view) {
54820510ec0a26e7eeb7f3a321deb755e984445fe74Brian Attwell        final InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
5496adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell                Context.INPUT_METHOD_SERVICE);
5506adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        if (imm != null) {
5516adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell            imm.showSoftInput(view, 0);
5526adbf1e7870e9de4ad203d334c8786ffca7d123dBrian Attwell        }
5534ba903cdf132a6be2e5efa33187b18ca8446e503Makoto Onuki    }
55435d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
55552aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private void saveLastTabPreference(int tab) {
55652aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann        mPrefs.edit().putInt(PERSISTENT_LAST_TAB, tab).apply();
55735d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    }
55835d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki
55952aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann    private int loadLastTabPreference() {
56035d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        try {
56152aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            return mPrefs.getInt(PERSISTENT_LAST_TAB, TabState.DEFAULT);
56235d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        } catch (IllegalArgumentException e) {
56335d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki            // Preference is corrupt?
56452aa32db432085ab2cd4864bd1edd1ef843da867Daniel Lehmann            return TabState.DEFAULT;
56535d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki        }
56635d4aec605ce915ff5c574892a2069a37e0b9a77Makoto Onuki    }
5673c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
5683c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void animateTabHeightChange(int start, int end) {
5693c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mPortraitTabs == null) {
5703c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            return;
5713c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
5723c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        final ValueAnimator animator = ValueAnimator.ofInt(start, end);
5733c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
5743c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            @Override
5753c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            public void onAnimationUpdate(ValueAnimator valueAnimator) {
5763c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                int value = (Integer) valueAnimator.getAnimatedValue();
5773c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell                setPortraitTabHeight(value);
5783c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            }
5793c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        });
5803c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        animator.setDuration(100).start();
5813c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
5823c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell
5833c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    private void setPortraitTabHeight(int height) {
5843c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        if (mPortraitTabs == null) {
5853c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell            return;
5863c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        }
5873c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        ViewGroup.LayoutParams layoutParams = mPortraitTabs.getLayoutParams();
5883c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        layoutParams.height = height;
5893c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell        mPortraitTabs.setLayoutParams(layoutParams);
5903c763b3a614375a1dbe273feec5a7664cd5939d3Brian Attwell    }
59108e1c4e49947daee26cfc435d01605febb7ae6faDmitri Plotnikov}
592