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