AllAppsSearchBarController.java revision 9e3fee1427c0baa38564e20a9f351d1a87c25761
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
180ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.content.Context;
19ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.graphics.Rect;
200ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.text.Editable;
210ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.text.TextWatcher;
220ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.view.KeyEvent;
23ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.View;
24ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport android.view.ViewGroup;
250ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.view.inputmethod.EditorInfo;
260ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.view.inputmethod.InputMethodManager;
270ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.widget.TextView;
280ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport android.widget.TextView.OnEditorActionListener;
29ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
300ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport com.android.launcher3.ExtendedEditText;
319e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyalimport com.android.launcher3.Launcher;
320ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalimport com.android.launcher3.Utilities;
335183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyalimport com.android.launcher3.util.ComponentKey;
345183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal
35ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chungimport java.util.ArrayList;
36ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
37ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung/**
38ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung * An interface to a search box that AllApps can command.
39ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung */
400ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyalpublic abstract class AllAppsSearchBarController
410ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
42ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
439e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal    protected Launcher mLauncher;
44ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    protected AlphabeticalAppsList mApps;
45ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    protected Callbacks mCb;
460ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    protected ExtendedEditText mInput;
470ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
480ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    protected DefaultAppSearchAlgorithm mSearchAlgorithm;
490ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    protected InputMethodManager mInputMethodManager;
50ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
51ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
52ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Sets the references to the apps model and the search result callback.
53ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
540ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public final void initialize(
550ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            AlphabeticalAppsList apps, ExtendedEditText input,
569e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal            Launcher launcher, Callbacks cb) {
57ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mApps = apps;
58ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        mCb = cb;
599e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal        mLauncher = launcher;
600ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
610ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput = input;
620ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput.addTextChangedListener(this);
630ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput.setOnEditorActionListener(this);
640ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput.setOnBackKeyListener(this);
650ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
660ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInputMethodManager = (InputMethodManager)
670ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal                mInput.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
680ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
690ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mSearchAlgorithm = onInitializeSearch();
70ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
71ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
724919827990b16ae22595d0b7cb123a875961d9beSunny Goyal    /**
730ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal     * To be overridden by subclasses. This method will get called when the controller is set.
744919827990b16ae22595d0b7cb123a875961d9beSunny Goyal     */
750ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    protected DefaultAppSearchAlgorithm onInitializeSearch() {
760ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        return null;
770ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
780ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
790ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    @Override
800ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
810ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // Do nothing
820ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
830ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
840ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    @Override
850ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void onTextChanged(CharSequence s, int start, int before, int count) {
860ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // Do nothing
870ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
880ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
890ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    @Override
900ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void afterTextChanged(final Editable s) {
910ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        String query = s.toString();
920ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (query.isEmpty()) {
930ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mSearchAlgorithm.cancel(true);
940ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mCb.clearSearchResult();
950ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        } else {
960ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mSearchAlgorithm.cancel(false);
970ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mSearchAlgorithm.doSearch(query, mCb);
980ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
990ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
1000ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1010ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    @Override
1020ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
1030ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // Skip if it's not the right action
1040ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (actionId != EditorInfo.IME_ACTION_SEARCH) {
1050ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            return false;
1060ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
1079e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal        // Skip if the query is empty
1089e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal        String query = v.getText().toString();
1099e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal        if (query.isEmpty()) {
1100ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            return false;
1110ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
1129e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal        return mLauncher.startActivitySafely(
1139e3fee1427c0baa38564e20a9f351d1a87c25761Sunny Goyal                v, AllAppsGridAdapter.createMarketSearchIntent(query), null);
1140ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
1150ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1160ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    @Override
1170ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public boolean onBackKey() {
1180ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // Only hide the search field if there is no query, or if there
1190ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        // are no filtered results
1200ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        String query = Utilities.trim(mInput.getEditableText().toString());
1210ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (query.isEmpty() || mApps.hasNoFilteredResults()) {
1220ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            reset();
1230ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            return true;
1240ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
1250ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        return false;
1260ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
1270ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1280ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    /**
1290ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal     * Resets the search bar state.
1300ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal     */
1310ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void reset() {
1320ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        unfocusSearchField();
1330ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mCb.clearSearchResult();
1340ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput.setText("");
1350ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
1360ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
1370ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
1380ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    protected void unfocusSearchField() {
1390ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        View nextFocus = mInput.focusSearch(View.FOCUS_DOWN);
1400ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (nextFocus != null) {
1410ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            nextFocus.requestFocus();
1420ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
1430ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
144ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
145ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
146ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Returns the search bar view.
147ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * @param parent the parent to attach the search bar view to.
148ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
1490ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public View getView(ViewGroup parent) {
1500ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        return null;
1510ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
152ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
153ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
154ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Focuses the search field to handle key events.
155ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
1560ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void focusSearchField() {
1570ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInput.requestFocus();
1580ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mInputMethodManager.showSoftInput(mInput, InputMethodManager.SHOW_IMPLICIT);
1590ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
160ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
161ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
162ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Returns whether the search field is focused.
163ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
1640ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public boolean isSearchFieldFocused() {
1650ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        return mInput.isFocused();
1660ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
167ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
168ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
169ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Returns whether the prediction bar should currently be visible depending on the state of
170ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * the search bar.
171ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
1720ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public boolean shouldShowPredictionBar() {
1730ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        return false;
1740ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
175ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
176ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
177ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Callback for getting search results.
178ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
179ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public interface Callbacks {
180ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
181ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        /**
182ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         * Called when the bounds of the search bar has changed.
183ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         */
184ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        void onBoundsChanged(Rect newBounds);
185ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
186ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        /**
187ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         * Called when the search is complete.
188ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         *
189ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         * @param apps sorted list of matching components or null if in case of failure.
190ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         */
1915183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        void onSearchResult(String query, ArrayList<ComponentKey> apps);
192ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
193ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        /**
194ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         * Called when the search results should be cleared.
195ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung         */
196ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        void clearSearchResult();
197ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
198ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung}