SearchBar.java revision 514bdd5473ae7f4da990d6035422d0784c6c344e
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.widget; 15 16import android.content.Context; 17import android.graphics.drawable.Drawable; 18import android.os.Handler; 19import android.os.SystemClock; 20import android.text.Editable; 21import android.text.TextUtils; 22import android.text.TextWatcher; 23import android.util.AttributeSet; 24import android.util.Log; 25import android.view.inputmethod.EditorInfo; 26import android.view.KeyEvent; 27import android.view.MotionEvent; 28import android.view.View; 29import android.widget.ImageView; 30import android.widget.RelativeLayout; 31import android.support.v17.leanback.R; 32import android.widget.TextView; 33 34/** 35 * SearchBar is a search widget. 36 */ 37public class SearchBar extends RelativeLayout { 38 private static final String TAG = SearchBar.class.getSimpleName(); 39 private static final boolean DEBUG = false; 40 41 /** 42 * Listener for search query changes 43 */ 44 public interface SearchBarListener { 45 46 /** 47 * Method invoked when the search bar detects a change in the query. 48 * 49 * @param query The current full query. 50 */ 51 public void onSearchQueryChange(String query); 52 53 /** 54 * Method invoked when the search query is submitted. 55 * 56 * @param query The query being submitted. 57 */ 58 public void onSearchQuerySubmit(String query); 59 60 /** 61 * Method invoked when the IME is being dismissed. 62 * 63 * @param query The query set in the search bar at the time the IME is being dismissed. 64 */ 65 public void onKeyboardDismiss(String query); 66 } 67 68 private SearchBarListener mSearchBarListener; 69 private SearchEditText mSearchTextEditor; 70 private ImageView mBadgeView; 71 private String mSearchQuery; 72 private String mTitle; 73 private Drawable mBadgeDrawable; 74 private final Handler mHandler = new Handler(); 75 76 public SearchBar(Context context) { 77 this(context, null); 78 } 79 80 public SearchBar(Context context, AttributeSet attrs) { 81 this(context, attrs, 0); 82 } 83 84 public SearchBar(Context context, AttributeSet attrs, int defStyle) { 85 super(context, attrs, defStyle); 86 mSearchQuery = ""; 87 } 88 89 @Override 90 protected void onFinishInflate() { 91 super.onFinishInflate(); 92 93 mSearchTextEditor = (SearchEditText)findViewById(R.id.lb_search_text_editor); 94 mBadgeView = (ImageView)findViewById(R.id.lb_search_bar_badge); 95 if (null != mBadgeDrawable) { 96 mBadgeView.setImageDrawable(mBadgeDrawable); 97 } 98 99 mSearchTextEditor.setOnFocusChangeListener(new OnFocusChangeListener() { 100 @Override 101 public void onFocusChange(View view, boolean hasFocus) { 102 if (DEBUG) Log.v(TAG, "onFocusChange " + hasFocus); 103 if (hasFocus) { 104 showNativeKeyboard(); 105 } 106 } 107 }); 108 mSearchTextEditor.addTextChangedListener(new TextWatcher() { 109 @Override 110 public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 111 112 } 113 114 @Override 115 public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 116 setSearchQuery(charSequence.toString()); 117 } 118 119 @Override 120 public void afterTextChanged(Editable editable) { 121 122 } 123 }); 124 mSearchTextEditor.setOnKeyboardDismissListener( 125 new SearchEditText.OnKeyboardDismissListener() { 126 @Override 127 public void onKeyboardDismiss() { 128 if (null != mSearchBarListener) { 129 mSearchBarListener.onKeyboardDismiss(mSearchQuery); 130 } 131 } 132 }); 133 mSearchTextEditor.setOnEditorActionListener(new TextView.OnEditorActionListener() { 134 @Override 135 public boolean onEditorAction(TextView textView, int action, KeyEvent keyEvent) { 136 if (EditorInfo.IME_ACTION_SEARCH == action && null != mSearchBarListener) { 137 mSearchBarListener.onSearchQuerySubmit(mSearchQuery); 138 return true; 139 } 140 return false; 141 } 142 }); 143 144 updateHint(); 145 } 146 147 @Override 148 protected void onAttachedToWindow() { 149 super.onAttachedToWindow(); 150 mHandler.post(new Runnable() { 151 @Override 152 public void run() { 153 mSearchTextEditor.requestFocus(); 154 mSearchTextEditor.requestFocusFromTouch(); 155 } 156 }); 157 } 158 159 /** 160 * Set a listener for when the term search changes 161 * @param listener 162 */ 163 public void setSearchBarListener(SearchBarListener listener) { 164 mSearchBarListener = listener; 165 } 166 167 /** 168 * Set the search query 169 * @param query the search query to use 170 */ 171 public void setSearchQuery(String query) { 172 if (query.equals(mSearchQuery)) { 173 return; 174 } 175 mSearchQuery = query; 176 if (null != mSearchBarListener) { 177 mSearchBarListener.onSearchQueryChange(mSearchQuery); 178 } 179 } 180 181 /** 182 * Set the title text used in the hint shown in the search bar. 183 * @param title The hint to use. 184 */ 185 public void setTitle(String title) { 186 mTitle = title; 187 updateHint(); 188 } 189 190 /** 191 * Returns the current title 192 */ 193 public String getTitle() { 194 return mTitle; 195 } 196 197 /** 198 * Set the badge drawable showing inside the search bar. 199 * @param drawable The drawable to be used in the search bar. 200 */ 201 public void setBadgeDrawable(Drawable drawable) { 202 mBadgeDrawable = drawable; 203 if (null != mBadgeView) { 204 mBadgeView.setImageDrawable(drawable); 205 if (null != drawable) { 206 mBadgeView.setVisibility(View.VISIBLE); 207 } else { 208 mBadgeView.setVisibility(View.GONE); 209 } 210 } 211 } 212 213 /** 214 * Returns the badge drawable 215 */ 216 public Drawable getBadgeDrawable() { 217 return mBadgeDrawable; 218 } 219 220 protected void showNativeKeyboard() { 221 mHandler.post(new Runnable() { 222 @Override 223 public void run() { 224 mSearchTextEditor.requestFocusFromTouch(); 225 mSearchTextEditor.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), 226 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 227 mSearchTextEditor.getWidth(), mSearchTextEditor.getHeight(), 0)); 228 mSearchTextEditor.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), 229 SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 230 mSearchTextEditor.getWidth(), mSearchTextEditor.getHeight(), 0)); 231 } 232 }); 233 } 234 235 /** 236 * This will update the hint for the search bar properly depending on state and provided title 237 */ 238 protected void updateHint() { 239 if (null == mSearchTextEditor) return; 240 241 String title = getResources().getString(R.string.lb_search_bar_hint); 242 if (!TextUtils.isEmpty(mTitle)) { 243 title = getResources().getString(R.string.lb_search_bar_hint_with_title, mTitle); 244 } 245 mSearchTextEditor.setHint(title); 246 } 247 248} 249