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