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