1ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung/*
2ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * Copyright (C) 2015 The Android Open Source Project
3ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung *
4ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * you may not use this file except in compliance with the License.
6ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * You may obtain a copy of the License at
7ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung *
8ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung *
10ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * Unless required by applicable law or agreed to in writing, software
11ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * See the License for the specific language governing permissions and
14ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * limitations under the License.
15ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung */
16ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungpackage com.android.launcher3.allapps;
17ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
18ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.content.Context;
19ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.text.Editable;
20ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.text.TextWatcher;
21ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.KeyEvent;
22ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.LayoutInflater;
23ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.View;
24ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.ViewGroup;
25ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.inputmethod.EditorInfo;
26ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.inputmethod.InputMethodManager;
27ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.widget.TextView;
28ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport com.android.launcher3.R;
29ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport com.android.launcher3.Utilities;
30ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport com.android.launcher3.util.Thunk;
31ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
32ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport java.util.List;
33ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
344919827990b16ae22595d0b7cb123a875961d9beSunny Goyal
35ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung/**
36ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * The default search controller.
37ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung */
38ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungfinal class DefaultAppSearchController extends AllAppsSearchBarController
39ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        implements TextWatcher, TextView.OnEditorActionListener, View.OnClickListener {
40ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
41ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
42ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
43ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private static final int FADE_IN_DURATION = 175;
44ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private static final int FADE_OUT_DURATION = 100;
45ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private static final int SEARCH_TRANSLATION_X_DP = 18;
46ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
47ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private final Context mContext;
48ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Thunk final InputMethodManager mInputMethodManager;
49ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
50ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private DefaultAppSearchAlgorithm mSearchManager;
51ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
52ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private ViewGroup mContainerView;
53ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private View mSearchView;
54ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Thunk View mSearchBarContainerView;
55ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private View mSearchButtonView;
56ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private View mDismissSearchButtonView;
57ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Thunk AllAppsSearchEditView mSearchBarEditView;
58ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Thunk AllAppsRecyclerView mAppsRecyclerView;
59383c507c47a5abf3258fc04220f37c366f983a97Sunny Goyal    @Thunk Runnable mFocusRecyclerViewRunnable = new Runnable() {
60ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        @Override
61ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        public void run() {
62ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mAppsRecyclerView.requestFocus();
63ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
64ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    };
65ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
66ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public DefaultAppSearchController(Context context, ViewGroup containerView,
67ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            AllAppsRecyclerView appsRecyclerView) {
68ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mContext = context;
69ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mInputMethodManager = (InputMethodManager)
70ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
71ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mContainerView = containerView;
72ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mAppsRecyclerView = appsRecyclerView;
73ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
74ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
75ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
76ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public View getView(ViewGroup parent) {
77ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
78ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchView = inflater.inflate(R.layout.all_apps_search_bar, parent, false);
79ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchView.setOnClickListener(this);
80ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
81ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchButtonView = mSearchView.findViewById(R.id.search_button);
82ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarContainerView = mSearchView.findViewById(R.id.search_container);
83ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button);
84ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mDismissSearchButtonView.setOnClickListener(this);
85ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarEditView = (AllAppsSearchEditView)
8601d4053436a6a771b36b527a4f0ff49bbf468632Winson Chung                mSearchBarContainerView.findViewById(R.id.search_box_input);
87ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarEditView.addTextChangedListener(this);
88ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarEditView.setOnEditorActionListener(this);
89ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarEditView.setOnBackKeyListener(
90ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                new AllAppsSearchEditView.OnBackKeyListener() {
91ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    @Override
92ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    public void onBackKey() {
93ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        // Only hide the search field if there is no query, or if there
94ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        // are no filtered results
95ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        String query = Utilities.trim(
96ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                                mSearchBarEditView.getEditableText().toString());
97ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        if (query.isEmpty() || mApps.hasNoFilteredResults()) {
98ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            hideSearchField(true, mFocusRecyclerViewRunnable);
99ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        }
100ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    }
101ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                });
102ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        return mSearchView;
103ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
104ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
105ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
106ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void focusSearchField() {
107ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarEditView.requestFocus();
108ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        showSearchField();
109ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
110ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
111ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
112ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public boolean isSearchFieldFocused() {
113ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        return mSearchBarEditView.isFocused();
114ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
115ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
116ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
1174919827990b16ae22595d0b7cb123a875961d9beSunny Goyal    protected void onInitialize() {
1184919827990b16ae22595d0b7cb123a875961d9beSunny Goyal        mSearchManager = new DefaultAppSearchAlgorithm(mApps.getApps());
1194919827990b16ae22595d0b7cb123a875961d9beSunny Goyal    }
1204919827990b16ae22595d0b7cb123a875961d9beSunny Goyal
1214919827990b16ae22595d0b7cb123a875961d9beSunny Goyal    @Override
122ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void reset() {
123ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        hideSearchField(false, null);
124ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
125ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
126ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
127ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public boolean shouldShowPredictionBar() {
1281ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung        return false;
129ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
130ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
131ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
132ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void onClick(View v) {
133ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (v == mSearchView) {
134ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            showSearchField();
135ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        } else if (v == mDismissSearchButtonView) {
136ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            hideSearchField(true, mFocusRecyclerViewRunnable);
137ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
138ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
139ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
140ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
141ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
142ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Do nothing
143ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
144ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
145ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
146ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void onTextChanged(CharSequence s, int start, int before, int count) {
147ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Do nothing
148ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
149ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
150ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
151ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void afterTextChanged(final Editable s) {
152ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        String query = s.toString();
153ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (query.isEmpty()) {
154ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchManager.cancel(true);
155ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mCb.clearSearchResult();
156ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        } else {
157ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchManager.cancel(false);
158ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchManager.doSearch(query, mCb);
159ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
160ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
161ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
162ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Override
163ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
164ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Skip if we disallow app-launch-on-enter
165ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (!ALLOW_SINGLE_APP_LAUNCH) {
166ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            return false;
167ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
168ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Skip if it's not the right action
169ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (actionId != EditorInfo.IME_ACTION_DONE) {
170ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            return false;
171ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
172ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Skip if there isn't exactly one item
173ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (mApps.getSize() != 1) {
174ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            return false;
175ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
176ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // If there is exactly one icon, then quick-launch it
177ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
178ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        for (int i = 0; i < items.size(); i++) {
179ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            AlphabeticalAppsList.AdapterItem item = items.get(i);
180ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE) {
181ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mAppsRecyclerView.getChildAt(i).performClick();
182ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mInputMethodManager.hideSoftInputFromWindow(
183ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        mContainerView.getWindowToken(), 0);
184ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                return true;
185ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            }
186ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
187ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        return false;
188ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
189ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
190ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
191ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Focuses the search field.
192ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
193ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    private void showSearchField() {
194ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Show the search bar and focus the search
195ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
196ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mContext.getResources().getDisplayMetrics());
197ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarContainerView.setVisibility(View.VISIBLE);
198ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarContainerView.setAlpha(0f);
199ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarContainerView.setTranslationX(translationX);
200ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchBarContainerView.animate()
201ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .alpha(1f)
202ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .translationX(0)
203ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .setDuration(FADE_IN_DURATION)
204ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .withLayer()
205ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .withEndAction(new Runnable() {
206ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    @Override
207ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    public void run() {
208ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        mSearchBarEditView.requestFocus();
209ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        mInputMethodManager.showSoftInput(mSearchBarEditView,
210ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                                InputMethodManager.SHOW_IMPLICIT);
211ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    }
212ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                });
213ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchButtonView.animate()
214ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .alpha(0f)
215ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .translationX(-translationX)
216ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .setDuration(FADE_OUT_DURATION)
217ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                .withLayer();
218ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
219ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
220ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
221ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Unfocuses the search field.
222ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
223ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    @Thunk void hideSearchField(boolean animated, final Runnable postAnimationRunnable) {
224ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mSearchManager.cancel(true);
225ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
226ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        final boolean resetTextField = mSearchBarEditView.getText().toString().length() > 0;
227ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
228ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mContext.getResources().getDisplayMetrics());
229ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (animated) {
230ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            // Hide the search bar and focus the recycler view
231ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchBarContainerView.animate()
232ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .alpha(0f)
233ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .translationX(0)
234ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .setDuration(FADE_IN_DURATION)
235ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .withLayer()
236ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .withEndAction(new Runnable() {
237ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        @Override
238ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        public void run() {
239ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            mSearchBarContainerView.setVisibility(View.INVISIBLE);
240ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            if (resetTextField) {
241ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                                mSearchBarEditView.setText("");
242ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            }
243ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            mCb.clearSearchResult();
244ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            if (postAnimationRunnable != null) {
245ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                                postAnimationRunnable.run();
246ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                            }
247ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                        }
248ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    });
249ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchButtonView.setTranslationX(-translationX);
250ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchButtonView.animate()
251ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .alpha(1f)
252ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .translationX(0)
253ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .setDuration(FADE_OUT_DURATION)
254ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                    .withLayer();
255ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        } else {
256ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchBarContainerView.setVisibility(View.INVISIBLE);
257ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            if (resetTextField) {
258ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                mSearchBarEditView.setText("");
259ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            }
260ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mCb.clearSearchResult();
261ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchButtonView.setAlpha(1f);
262ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            mSearchButtonView.setTranslationX(0f);
263ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            if (postAnimationRunnable != null) {
264ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung                postAnimationRunnable.run();
265ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung            }
266ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        }
267ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mInputMethodManager.hideSoftInputFromWindow(mContainerView.getWindowToken(), 0);
268ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
269ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung}
270