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