AllAppsSearchBarController.java revision 9e3fee1427c0baa38564e20a9f351d1a87c25761
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 */
16package com.android.launcher3.allapps;
17
18import android.content.Context;
19import android.graphics.Rect;
20import android.text.Editable;
21import android.text.TextWatcher;
22import android.view.KeyEvent;
23import android.view.View;
24import android.view.ViewGroup;
25import android.view.inputmethod.EditorInfo;
26import android.view.inputmethod.InputMethodManager;
27import android.widget.TextView;
28import android.widget.TextView.OnEditorActionListener;
29
30import com.android.launcher3.ExtendedEditText;
31import com.android.launcher3.Launcher;
32import com.android.launcher3.Utilities;
33import com.android.launcher3.util.ComponentKey;
34
35import java.util.ArrayList;
36
37/**
38 * An interface to a search box that AllApps can command.
39 */
40public abstract class AllAppsSearchBarController
41        implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
42
43    protected Launcher mLauncher;
44    protected AlphabeticalAppsList mApps;
45    protected Callbacks mCb;
46    protected ExtendedEditText mInput;
47
48    protected DefaultAppSearchAlgorithm mSearchAlgorithm;
49    protected InputMethodManager mInputMethodManager;
50
51    /**
52     * Sets the references to the apps model and the search result callback.
53     */
54    public final void initialize(
55            AlphabeticalAppsList apps, ExtendedEditText input,
56            Launcher launcher, Callbacks cb) {
57        mApps = apps;
58        mCb = cb;
59        mLauncher = launcher;
60
61        mInput = input;
62        mInput.addTextChangedListener(this);
63        mInput.setOnEditorActionListener(this);
64        mInput.setOnBackKeyListener(this);
65
66        mInputMethodManager = (InputMethodManager)
67                mInput.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
68
69        mSearchAlgorithm = onInitializeSearch();
70    }
71
72    /**
73     * To be overridden by subclasses. This method will get called when the controller is set.
74     */
75    protected DefaultAppSearchAlgorithm onInitializeSearch() {
76        return null;
77    }
78
79    @Override
80    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
81        // Do nothing
82    }
83
84    @Override
85    public void onTextChanged(CharSequence s, int start, int before, int count) {
86        // Do nothing
87    }
88
89    @Override
90    public void afterTextChanged(final Editable s) {
91        String query = s.toString();
92        if (query.isEmpty()) {
93            mSearchAlgorithm.cancel(true);
94            mCb.clearSearchResult();
95        } else {
96            mSearchAlgorithm.cancel(false);
97            mSearchAlgorithm.doSearch(query, mCb);
98        }
99    }
100
101    @Override
102    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
103        // Skip if it's not the right action
104        if (actionId != EditorInfo.IME_ACTION_SEARCH) {
105            return false;
106        }
107        // Skip if the query is empty
108        String query = v.getText().toString();
109        if (query.isEmpty()) {
110            return false;
111        }
112        return mLauncher.startActivitySafely(
113                v, AllAppsGridAdapter.createMarketSearchIntent(query), null);
114    }
115
116    @Override
117    public boolean onBackKey() {
118        // Only hide the search field if there is no query, or if there
119        // are no filtered results
120        String query = Utilities.trim(mInput.getEditableText().toString());
121        if (query.isEmpty() || mApps.hasNoFilteredResults()) {
122            reset();
123            return true;
124        }
125        return false;
126    }
127
128    /**
129     * Resets the search bar state.
130     */
131    public void reset() {
132        unfocusSearchField();
133        mCb.clearSearchResult();
134        mInput.setText("");
135        mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
136    }
137
138    protected void unfocusSearchField() {
139        View nextFocus = mInput.focusSearch(View.FOCUS_DOWN);
140        if (nextFocus != null) {
141            nextFocus.requestFocus();
142        }
143    }
144
145    /**
146     * Returns the search bar view.
147     * @param parent the parent to attach the search bar view to.
148     */
149    public View getView(ViewGroup parent) {
150        return null;
151    }
152
153    /**
154     * Focuses the search field to handle key events.
155     */
156    public void focusSearchField() {
157        mInput.requestFocus();
158        mInputMethodManager.showSoftInput(mInput, InputMethodManager.SHOW_IMPLICIT);
159    }
160
161    /**
162     * Returns whether the search field is focused.
163     */
164    public boolean isSearchFieldFocused() {
165        return mInput.isFocused();
166    }
167
168    /**
169     * Returns whether the prediction bar should currently be visible depending on the state of
170     * the search bar.
171     */
172    public boolean shouldShowPredictionBar() {
173        return false;
174    }
175
176    /**
177     * Callback for getting search results.
178     */
179    public interface Callbacks {
180
181        /**
182         * Called when the bounds of the search bar has changed.
183         */
184        void onBoundsChanged(Rect newBounds);
185
186        /**
187         * Called when the search is complete.
188         *
189         * @param apps sorted list of matching components or null if in case of failure.
190         */
191        void onSearchResult(String query, ArrayList<ComponentKey> apps);
192
193        /**
194         * Called when the search results should be cleared.
195         */
196        void clearSearchResult();
197    }
198}