• 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.search;
17 
18 import android.text.Editable;
19 import android.text.SpannableStringBuilder;
20 import android.text.TextUtils;
21 import android.text.TextWatcher;
22 import android.text.style.SuggestionSpan;
23 import android.util.Log;
24 import android.view.KeyEvent;
25 import android.view.inputmethod.EditorInfo;
26 import android.widget.TextView;
27 import android.widget.TextView.OnEditorActionListener;
28 
29 import com.android.launcher3.ExtendedEditText;
30 import com.android.launcher3.Utilities;
31 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
32 import com.android.launcher3.search.SearchAlgorithm;
33 import com.android.launcher3.search.SearchCallback;
34 import com.android.launcher3.views.ActivityContext;
35 
36 /**
37  * An interface to a search box that AllApps can command.
38  */
39 public class AllAppsSearchBarController
40         implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
41 
42     private static final String TAG = "AllAppsSearchBarController";
43     protected ActivityContext mLauncher;
44     protected SearchCallback<AdapterItem> mCallback;
45     protected ExtendedEditText mInput;
46     protected String mQuery;
47     private String[] mTextConversions;
48 
49     protected SearchAlgorithm<AdapterItem> mSearchAlgorithm;
50 
setVisibility(int visibility)51     public void setVisibility(int visibility) {
52         mInput.setVisibility(visibility);
53     }
54 
55     /**
56      * Sets the references to the apps model and the search result callback.
57      */
initialize( SearchAlgorithm<AdapterItem> searchAlgorithm, ExtendedEditText input, ActivityContext launcher, SearchCallback<AdapterItem> callback)58     public final void initialize(
59             SearchAlgorithm<AdapterItem> searchAlgorithm, ExtendedEditText input,
60             ActivityContext launcher, SearchCallback<AdapterItem> callback) {
61         mCallback = callback;
62         mLauncher = launcher;
63 
64         mInput = input;
65         mInput.addTextChangedListener(this);
66         mInput.setOnEditorActionListener(this);
67         mInput.setOnBackKeyListener(this);
68         mSearchAlgorithm = searchAlgorithm;
69     }
70 
71     @Override
beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)72     public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
73         // Do nothing
74     }
75 
76     @Override
onTextChanged(CharSequence s, int start, int before, int count)77     public void onTextChanged(CharSequence s, int start, int before, int count) {
78         mTextConversions = extractTextConversions(s);
79     }
80 
81     /**
82      * Extract text conversions from composing text and send them for search.
83      */
extractTextConversions(CharSequence text)84     public static String[] extractTextConversions(CharSequence text) {
85         if (text instanceof SpannableStringBuilder) {
86             SpannableStringBuilder spanned = (SpannableStringBuilder) text;
87             SuggestionSpan[] suggestionSpans =
88                 spanned.getSpans(0, text.length(), SuggestionSpan.class);
89             if (suggestionSpans != null && suggestionSpans.length > 0) {
90                 spanned.removeSpan(suggestionSpans[0]);
91                 return suggestionSpans[0].getSuggestions();
92             }
93         }
94         return null;
95     }
96 
97     @Override
afterTextChanged(final Editable s)98     public void afterTextChanged(final Editable s) {
99         mQuery = s.toString();
100         if (mQuery.isEmpty()) {
101             mSearchAlgorithm.cancel(true);
102             mCallback.clearSearchResult();
103         } else {
104             mSearchAlgorithm.cancel(false);
105             mSearchAlgorithm.doSearch(mQuery, mTextConversions, mCallback);
106         }
107     }
108 
refreshSearchResult()109     public void refreshSearchResult() {
110         if (TextUtils.isEmpty(mQuery)) {
111             return;
112         }
113         // If play store continues auto updating an app, we want to show partial result.
114         mSearchAlgorithm.cancel(false);
115         mSearchAlgorithm.doSearch(mQuery, mCallback);
116     }
117 
118     @Override
onEditorAction(TextView v, int actionId, KeyEvent event)119     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
120 
121         if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO || (
122                 actionId == EditorInfo.IME_NULL && event != null
123                         && event.getAction() == KeyEvent.ACTION_DOWN)) {
124             if (actionId == EditorInfo.IME_NULL) {
125                 Log.i(TAG, "User pressed ENTER key");
126             } else {
127                 Log.i(TAG, "User tapped ime search button");
128             }
129             // selectFocusedView should return SearchTargetEvent that is passed onto onClick
130             return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
131         }
132         return false;
133     }
134 
135     @Override
onBackKey()136     public boolean onBackKey() {
137         // Only hide the search field if there is no query
138         String query = Utilities.trim(mInput.getEditableText().toString());
139         if (query.isEmpty()) {
140             reset();
141             return true;
142         }
143         return false;
144     }
145 
146     /**
147      * Resets the search bar state.
148      */
reset()149     public void reset() {
150         mCallback.clearSearchResult();
151         mInput.reset();
152         mInput.clearFocus();
153         mInput.hideKeyboard();
154         mQuery = null;
155     }
156 
157     /**
158      * Focuses the search field to handle key events.
159      */
focusSearchField()160     public void focusSearchField() {
161         mInput.showKeyboard();
162     }
163 
164     /**
165      * Returns whether the search field is focused.
166      */
isSearchFieldFocused()167     public boolean isSearchFieldFocused() {
168         return mInput.isFocused();
169     }
170 }
171