• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.allapps;
17 
18 import android.content.Context;
19 import android.content.Intent;
20 import android.graphics.Rect;
21 import android.net.Uri;
22 import android.text.Editable;
23 import android.text.TextUtils;
24 import android.text.TextWatcher;
25 import android.view.KeyEvent;
26 import android.view.View;
27 import android.view.inputmethod.EditorInfo;
28 import android.view.inputmethod.InputMethodManager;
29 import android.widget.TextView;
30 import android.widget.TextView.OnEditorActionListener;
31 
32 import com.android.launcher3.ExtendedEditText;
33 import com.android.launcher3.Launcher;
34 import com.android.launcher3.Utilities;
35 import com.android.launcher3.util.ComponentKey;
36 
37 import java.util.ArrayList;
38 
39 /**
40  * An interface to a search box that AllApps can command.
41  */
42 public abstract class AllAppsSearchBarController
43         implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
44 
45     protected Launcher mLauncher;
46     protected AlphabeticalAppsList mApps;
47     protected Callbacks mCb;
48     protected ExtendedEditText mInput;
49     private String mQuery;
50 
51     protected DefaultAppSearchAlgorithm mSearchAlgorithm;
52     protected InputMethodManager mInputMethodManager;
53 
setVisibility(int visibility)54     public void setVisibility(int visibility) {
55         mInput.setVisibility(visibility);
56     }
57     /**
58      * Sets the references to the apps model and the search result callback.
59      */
initialize( AlphabeticalAppsList apps, ExtendedEditText input, Launcher launcher, Callbacks cb)60     public final void initialize(
61             AlphabeticalAppsList apps, ExtendedEditText input,
62             Launcher launcher, Callbacks cb) {
63         mApps = apps;
64         mCb = cb;
65         mLauncher = launcher;
66 
67         mInput = input;
68         mInput.addTextChangedListener(this);
69         mInput.setOnEditorActionListener(this);
70         mInput.setOnBackKeyListener(this);
71 
72         mInputMethodManager = (InputMethodManager)
73                 mInput.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
74 
75         mSearchAlgorithm = onInitializeSearch();
76     }
77 
78     /**
79      * To be implemented by subclasses. This method will get called when the controller is set.
80      */
onInitializeSearch()81     protected abstract DefaultAppSearchAlgorithm onInitializeSearch();
82 
83     @Override
beforeTextChanged(CharSequence s, int start, int count, int after)84     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
85         // Do nothing
86     }
87 
88     @Override
onTextChanged(CharSequence s, int start, int before, int count)89     public void onTextChanged(CharSequence s, int start, int before, int count) {
90         // Do nothing
91     }
92 
93     @Override
afterTextChanged(final Editable s)94     public void afterTextChanged(final Editable s) {
95         mQuery = s.toString();
96         if (mQuery.isEmpty()) {
97             mSearchAlgorithm.cancel(true);
98             mCb.clearSearchResult();
99         } else {
100             mSearchAlgorithm.cancel(false);
101             mSearchAlgorithm.doSearch(mQuery, mCb);
102         }
103     }
104 
refreshSearchResult()105     protected void refreshSearchResult() {
106         if (TextUtils.isEmpty(mQuery)) {
107             return;
108         }
109         // If play store continues auto updating an app, we want to show partial result.
110         mSearchAlgorithm.cancel(false);
111         mSearchAlgorithm.doSearch(mQuery, mCb);
112     }
113 
114     @Override
onEditorAction(TextView v, int actionId, KeyEvent event)115     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
116         // Skip if it's not the right action
117         if (actionId != EditorInfo.IME_ACTION_SEARCH) {
118             return false;
119         }
120         // Skip if the query is empty
121         String query = v.getText().toString();
122         if (query.isEmpty()) {
123             return false;
124         }
125         return mLauncher.startActivitySafely(v, createMarketSearchIntent(query), null);
126     }
127 
128     @Override
onBackKey()129     public boolean onBackKey() {
130         // Only hide the search field if there is no query
131         String query = Utilities.trim(mInput.getEditableText().toString());
132         if (query.isEmpty()) {
133             reset();
134             return true;
135         }
136         return false;
137     }
138 
139     /**
140      * Resets the search bar state.
141      */
reset()142     public void reset() {
143         unfocusSearchField();
144         mCb.clearSearchResult();
145         mInput.setText("");
146         mQuery = null;
147         hideKeyboard();
148     }
149 
hideKeyboard()150     protected void hideKeyboard() {
151         mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
152     }
153 
unfocusSearchField()154     protected void unfocusSearchField() {
155         View nextFocus = mInput.focusSearch(View.FOCUS_DOWN);
156         if (nextFocus != null) {
157             nextFocus.requestFocus();
158         }
159     }
160 
161     /**
162      * Focuses the search field to handle key events.
163      */
focusSearchField()164     public void focusSearchField() {
165         mInput.showKeyboard();
166     }
167 
168     /**
169      * Returns whether the search field is focused.
170      */
isSearchFieldFocused()171     public boolean isSearchFieldFocused() {
172         return mInput.isFocused();
173     }
174 
175     /**
176      * Creates a new market search intent.
177      */
createMarketSearchIntent(String query)178     public Intent createMarketSearchIntent(String query) {
179         Uri marketSearchUri = Uri.parse("market://search")
180                 .buildUpon()
181                 .appendQueryParameter("c", "apps")
182                 .appendQueryParameter("q", query)
183                 .build();
184         return new Intent(Intent.ACTION_VIEW).setData(marketSearchUri);
185     }
186 
187     /**
188      * Callback for getting search results.
189      */
190     public interface Callbacks {
191 
192         /**
193          * Called when the bounds of the search bar has changed.
194          */
195         @Deprecated
onBoundsChanged(Rect newBounds)196         void onBoundsChanged(Rect newBounds);
197 
198         /**
199          * Called when the search is complete.
200          *
201          * @param apps sorted list of matching components or null if in case of failure.
202          */
onSearchResult(String query, ArrayList<ComponentKey> apps)203         void onSearchResult(String query, ArrayList<ComponentKey> apps);
204 
205         /**
206          * Called when the search results should be cleared.
207          */
clearSearchResult()208         void clearSearchResult();
209     }
210 }