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.search; 17 18import android.support.annotation.NonNull; 19import android.support.annotation.Nullable; 20import android.text.Editable; 21import android.text.TextUtils; 22import android.text.TextWatcher; 23import android.view.KeyEvent; 24import android.view.inputmethod.EditorInfo; 25import android.widget.TextView; 26import android.widget.TextView.OnEditorActionListener; 27 28import com.android.launcher3.ExtendedEditText; 29import com.android.launcher3.Launcher; 30import com.android.launcher3.Utilities; 31import com.android.launcher3.util.ComponentKey; 32import com.android.launcher3.util.PackageManagerHelper; 33 34import java.util.ArrayList; 35 36/** 37 * An interface to a search box that AllApps can command. 38 */ 39public class AllAppsSearchBarController 40 implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener { 41 42 protected Launcher mLauncher; 43 protected Callbacks mCb; 44 protected ExtendedEditText mInput; 45 protected String mQuery; 46 47 protected SearchAlgorithm mSearchAlgorithm; 48 49 public void setVisibility(int visibility) { 50 mInput.setVisibility(visibility); 51 } 52 /** 53 * Sets the references to the apps model and the search result callback. 54 */ 55 public final void initialize( 56 SearchAlgorithm searchAlgorithm, ExtendedEditText input, 57 Launcher launcher, Callbacks cb) { 58 mCb = cb; 59 mLauncher = launcher; 60 61 mInput = input; 62 mInput.addTextChangedListener(this); 63 mInput.setOnEditorActionListener(this); 64 mInput.setOnBackKeyListener(this); 65 mSearchAlgorithm = searchAlgorithm; 66 } 67 68 @Override 69 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 70 // Do nothing 71 } 72 73 @Override 74 public void onTextChanged(CharSequence s, int start, int before, int count) { 75 // Do nothing 76 } 77 78 @Override 79 public void afterTextChanged(final Editable s) { 80 mQuery = s.toString(); 81 if (mQuery.isEmpty()) { 82 mSearchAlgorithm.cancel(true); 83 mCb.clearSearchResult(); 84 } else { 85 mSearchAlgorithm.cancel(false); 86 mSearchAlgorithm.doSearch(mQuery, mCb); 87 } 88 } 89 90 public void refreshSearchResult() { 91 if (TextUtils.isEmpty(mQuery)) { 92 return; 93 } 94 // If play store continues auto updating an app, we want to show partial result. 95 mSearchAlgorithm.cancel(false); 96 mSearchAlgorithm.doSearch(mQuery, mCb); 97 } 98 99 @Override 100 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 101 // Skip if it's not the right action 102 if (actionId != EditorInfo.IME_ACTION_SEARCH) { 103 return false; 104 } 105 106 // Skip if the query is empty 107 String query = v.getText().toString(); 108 if (query.isEmpty()) { 109 return false; 110 } 111 return mLauncher.startActivitySafely(v, 112 PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null); 113 } 114 115 @Override 116 public boolean onBackKey() { 117 // Only hide the search field if there is no query 118 String query = Utilities.trim(mInput.getEditableText().toString()); 119 if (query.isEmpty()) { 120 reset(); 121 return true; 122 } 123 return false; 124 } 125 126 /** 127 * Resets the search bar state. 128 */ 129 public void reset() { 130 mCb.clearSearchResult(); 131 mInput.reset(); 132 mQuery = null; 133 } 134 135 /** 136 * Focuses the search field to handle key events. 137 */ 138 public void focusSearchField() { 139 mInput.showKeyboard(); 140 } 141 142 /** 143 * Returns whether the search field is focused. 144 */ 145 public boolean isSearchFieldFocused() { 146 return mInput.isFocused(); 147 } 148 149 /** 150 * Callback for getting search results. 151 */ 152 public interface Callbacks { 153 154 /** 155 * Called when the search is complete. 156 * 157 * @param apps sorted list of matching components or null if in case of failure. 158 */ 159 void onSearchResult(String query, ArrayList<ComponentKey> apps); 160 161 /** 162 * Called when the search results should be cleared. 163 */ 164 void clearSearchResult(); 165 } 166 167}