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}