19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.app; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani 20d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasaniimport android.content.BroadcastReceiver; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 22444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertimport android.content.Context; 23444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertimport android.content.Intent; 24d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasaniimport android.content.IntentFilter; 25875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.pm.ActivityInfo; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 27c1f40960644b461b108480b6446c89963441492dBjorn Bringertimport android.content.pm.PackageManager.NameNotFoundException; 28d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasaniimport android.content.res.Configuration; 29444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertimport android.graphics.drawable.Drawable; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.speech.RecognizerIntent; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 378abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powellimport android.util.TypedValue; 388abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powellimport android.view.ActionMode; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 41875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.view.MotionEvent; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 43875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.view.ViewConfiguration; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Window; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager; 47a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackbornimport android.view.inputmethod.InputMethodManager; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.AutoCompleteTextView; 49da5c1bd4443b5b569a0d392cd53b476b4e160c47Bjorn Bringertimport android.widget.ImageView; 50077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringertimport android.widget.LinearLayout; 51968ec938399033d280b1648123104ac567f2a093Amith Yamasaniimport android.widget.SearchView; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.TextView; 53968ec938399033d280b1648123104ac567f2a093Amith Yamasani 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 55e9ce3f01d42769f03f10e70c3244500e92d7eee1Amith Yamasani * Search dialog. This is controlled by the 56e9ce3f01d42769f03f10e70c3244500e92d7eee1Amith Yamasani * SearchManager and runs in the current foreground process. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 60968ec938399033d280b1648123104ac567f2a093Amith Yamasanipublic class SearchDialog extends Dialog { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Debugging support 63875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final boolean DBG = false; 64875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final String LOG_TAG = "SearchDialog"; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String INSTANCE_KEY_COMPONENT = "comp"; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String INSTANCE_KEY_APPDATA = "data"; 68b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert private static final String INSTANCE_KEY_USER_QUERY = "uQry"; 69968ec938399033d280b1648123104ac567f2a093Amith Yamasani 707df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau // The string used for privateImeOptions to identify to the IME that it should not show 717df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau // a microphone button since one already exists in the search dialog. 727df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau private static final String IME_OPTION_NO_MICROPHONE = "nm"; 73b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert 741fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau private static final int SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL = 7; 75444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // views & widgets 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private TextView mBadgeLabel; 78da5c1bd4443b5b569a0d392cd53b476b4e160c47Bjorn Bringert private ImageView mAppIcon; 79968ec938399033d280b1648123104ac567f2a093Amith Yamasani private AutoCompleteTextView mSearchAutoComplete; 80875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private View mSearchPlate; 81968ec938399033d280b1648123104ac567f2a093Amith Yamasani private SearchView mSearchView; 82f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy private Drawable mWorkingSpinner; 83246529891ee289e8393ad4a486db785ef455c778Amith Yamasani private View mCloseSearch; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // interaction with searchable application 86875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private SearchableInfo mSearchable; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ComponentName mLaunchComponent; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Bundle mAppSearchData; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mActivityContext; 90875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For voice searching 92f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney private final Intent mVoiceWebSearchIntent; 93f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney private final Intent mVoiceAppSearchIntent; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 95875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // The query entered by the user. This is not changed when selecting a suggestion 96875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // that modifies the contents of the text field. But if the user then edits 97875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // the suggestion, the resulting string is saved. 98875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private String mUserQuery; 99662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath 100662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath // Last known IME options value for the search edit text. 101662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath private int mSearchAutoCompleteImeOptions; 102662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath 1034986044fd3bce877247e425374b47967775081a8Amith Yamasani private BroadcastReceiver mConfChangeListener = new BroadcastReceiver() { 1044986044fd3bce877247e425374b47967775081a8Amith Yamasani @Override 1054986044fd3bce877247e425374b47967775081a8Amith Yamasani public void onReceive(Context context, Intent intent) { 1064986044fd3bce877247e425374b47967775081a8Amith Yamasani if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 1074986044fd3bce877247e425374b47967775081a8Amith Yamasani onConfigurationChanged(); 1084986044fd3bce877247e425374b47967775081a8Amith Yamasani } 1094986044fd3bce877247e425374b47967775081a8Amith Yamasani } 1104986044fd3bce877247e425374b47967775081a8Amith Yamasani }; 1114986044fd3bce877247e425374b47967775081a8Amith Yamasani 1128abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell static int resolveDialogTheme(Context context) { 1138abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell TypedValue outValue = new TypedValue(); 1148abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell context.getTheme().resolveAttribute(com.android.internal.R.attr.searchDialogTheme, 1158abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell outValue, true); 1168abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell return outValue.resourceId; 1178abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell } 1188abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor - fires it up and makes it look like the search UI. 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Application Context we can use for system acess 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 124e9ce3f01d42769f03f10e70c3244500e92d7eee1Amith Yamasani public SearchDialog(Context context, SearchManager searchManager) { 1258abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell super(context, resolveDialogTheme(context)); 126f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney 127f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney // Save voice intent for later queries/launching 128f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 129f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 130f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 131f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); 132f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney 133f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 134f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 138f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney * Create the search dialog and any resources that are used for the 139f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney * entire lifetime of the dialog. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onCreate(Bundle savedInstanceState) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onCreate(savedInstanceState); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1458d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert Window theWindow = getWindow(); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WindowManager.LayoutParams lp = theWindow.getAttributes(); 147980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy lp.width = ViewGroup.LayoutParams.MATCH_PARENT; 1488d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert // taking up the whole window (even when transparent) is less than ideal, 1498d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert // but necessary to show the popup window until the window manager supports 1508d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert // having windows anchored by their parent but not clipped by them. 151980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy lp.height = ViewGroup.LayoutParams.MATCH_PARENT; 1528d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; 15398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project theWindow.setAttributes(lp); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 156f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney // Touching outside of the search dialog will dismiss it 157f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney setCanceledOnTouchOutside(true); 158f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney } 159f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney 160f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney /** 161f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney * We recreate the dialog view each time it becomes visible so as to limit 162f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney * the scope of any problems with the contained resources. 163f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney */ 164f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney private void createContentView() { 165f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney setContentView(com.android.internal.R.layout.search_bar); 166f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get the view elements for local access 168077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar); 169077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert searchBar.setSearchDialog(this); 170968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view); 171b4569fb17fada4fdc43e4f4dbfbc79bb097a1f74Amith Yamasani mSearchView.setIconified(false); 172968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchView.setOnCloseListener(mOnCloseListener); 17301f21354654a315ea2a2a1668bbda50645123d4aAdam Powell mSearchView.setOnQueryTextListener(mOnQueryChangeListener); 17401f21354654a315ea2a2a1668bbda50645123d4aAdam Powell mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener); 1756a7421ba94b1fca0a20ddf146054ebd771ee471eAmith Yamasani mSearchView.onActionViewExpanded(); 176968ec938399033d280b1648123104ac567f2a093Amith Yamasani 177246529891ee289e8393ad4a486db785ef455c778Amith Yamasani mCloseSearch = findViewById(com.android.internal.R.id.closeButton); 178246529891ee289e8393ad4a486db785ef455c778Amith Yamasani mCloseSearch.setOnClickListener(new View.OnClickListener() { 179246529891ee289e8393ad4a486db785ef455c778Amith Yamasani @Override 180246529891ee289e8393ad4a486db785ef455c778Amith Yamasani public void onClick(View v) { 181246529891ee289e8393ad4a486db785ef455c778Amith Yamasani dismiss(); 182246529891ee289e8393ad4a486db785ef455c778Amith Yamasani } 183246529891ee289e8393ad4a486db785ef455c778Amith Yamasani }); 184246529891ee289e8393ad4a486db785ef455c778Amith Yamasani 185968ec938399033d280b1648123104ac567f2a093Amith Yamasani // TODO: Move the badge logic to SearchView or move the badge to search_bar.xml 186968ec938399033d280b1648123104ac567f2a093Amith Yamasani mBadgeLabel = (TextView) mSearchView.findViewById(com.android.internal.R.id.search_badge); 187968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchAutoComplete = (AutoCompleteTextView) 188968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchView.findViewById(com.android.internal.R.id.search_src_text); 189da5c1bd4443b5b569a0d392cd53b476b4e160c47Bjorn Bringert mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon); 190968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchPlate = mSearchView.findViewById(com.android.internal.R.id.search_plate); 191f4f7046183f0daedd17703fa16cf9026442bdaeeRomain Guy mWorkingSpinner = getContext().getResources(). 1921480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau getDrawable(com.android.internal.R.drawable.search_spinner); 193a40d7ec7ef5f57d61cc3dcc954009593c7829c70Amith Yamasani // TODO: Restore the spinner for slow suggestion lookups 194a40d7ec7ef5f57d61cc3dcc954009593c7829c70Amith Yamasani // mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds( 195a40d7ec7ef5f57d61cc3dcc954009593c7829c70Amith Yamasani // null, null, mWorkingSpinner, null); 196dfcbc046d7fcd74c8aacd9f26bd48084900d3b4aBryan Mawhinney setWorking(false); 197dfcbc046d7fcd74c8aacd9f26bd48084900d3b4aBryan Mawhinney 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pre-hide all the extraneous elements 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBadgeLabel.setVisibility(View.GONE); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Additional adjustments to make Dialog work for Search 202662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath mSearchAutoCompleteImeOptions = mSearchAutoComplete.getImeOptions(); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set up the search dialog 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 208875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @return true if search dialog launched, false if not 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean show(String initialQuery, boolean selectInitialQuery, 211479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani ComponentName componentName, Bundle appSearchData) { 212479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData); 213fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath if (success) { 214fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath // Display the drop down as soon as possible instead of waiting for the rest of the 215fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath // pending UI stuff to get done, so that things appear faster to the user. 216fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath mSearchAutoComplete.showDropDownAfterLayout(); 217fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath } 218fef8d3e4d8f6f46c098d04b3a57409c947ec1c75Satish Sampath return success; 219b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau } 220da1f4b669ead7813079643b43301f100127aaeedBjorn Bringert 221b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau /** 222479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani * Does the rest of the work required to show the search dialog. Called by 223479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani * {@link #show(String, boolean, ComponentName, Bundle)} and 224479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani * 225b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau * @return true if search dialog showed, false if not 226b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau */ 227b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau private boolean doShow(String initialQuery, boolean selectInitialQuery, 228479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani ComponentName componentName, Bundle appSearchData) { 229875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // set up the searchable and show the dialog 230479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani if (!show(componentName, appSearchData)) { 231875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return false; 232875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 233b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau 234875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // finally, load the user's initial text (which may trigger suggestions) 235875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen setUserQuery(initialQuery); 236875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (selectInitialQuery) { 237875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mSearchAutoComplete.selectAll(); 238875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 239b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau 240875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return true; 241875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 242b3aab6958120ad8bc8d70c493ebf49dcb4fbc30eMike LeBeau 243875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 244875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Sets up the search dialog and shows it. 245875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 246875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @return <code>true</code> if search dialog launched 247875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 248479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani private boolean show(ComponentName componentName, Bundle appSearchData) { 249875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 250875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (DBG) { 251875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen Log.d(LOG_TAG, "show(" + componentName + ", " 252479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani + appSearchData + ")"); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 254875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 2558d1538237847baf381787b881141f8c0478bef5bBjorn Bringert SearchManager searchManager = (SearchManager) 2568d1538237847baf381787b881141f8c0478bef5bBjorn Bringert mContext.getSystemService(Context.SEARCH_SERVICE); 257479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // Try to get the searchable info for the provided component. 2586cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert mSearchable = searchManager.getSearchableInfo(componentName); 259ee716fa2b03666622a73f8cc54dae4afd091353dBjorn Bringert 260ee716fa2b03666622a73f8cc54dae4afd091353dBjorn Bringert if (mSearchable == null) { 261ee716fa2b03666622a73f8cc54dae4afd091353dBjorn Bringert return false; 262ee716fa2b03666622a73f8cc54dae4afd091353dBjorn Bringert } 263ee716fa2b03666622a73f8cc54dae4afd091353dBjorn Bringert 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchComponent = componentName; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAppSearchData = appSearchData; 266875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mActivityContext = mSearchable.getActivityContext(getContext()); 267f36740b2e4a9a187bf688c632c1d0a7ae926c96aBryan Mawhinney 268875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // show the dialog. this will call onStart(). 26911f09bb5cd45a76ae7757b6f20807e836c3692f8Bjorn Bringert if (!isShowing()) { 27011f09bb5cd45a76ae7757b6f20807e836c3692f8Bjorn Bringert // Recreate the search bar view every time the dialog is shown, to get rid 27111f09bb5cd45a76ae7757b6f20807e836c3692f8Bjorn Bringert // of any bad state in the AutoCompleteTextView etc 27211f09bb5cd45a76ae7757b6f20807e836c3692f8Bjorn Bringert createContentView(); 273968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchView.setSearchableInfo(mSearchable); 274940ef38c7c46565a8f8fdd6bb8e0183646d0abdcAmith Yamasani mSearchView.setAppSearchData(mAppSearchData); 27511f09bb5cd45a76ae7757b6f20807e836c3692f8Bjorn Bringert 276875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen show(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 278875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen updateUI(); 2794986044fd3bce877247e425374b47967775081a8Amith Yamasani 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2834986044fd3bce877247e425374b47967775081a8Amith Yamasani @Override 2844986044fd3bce877247e425374b47967775081a8Amith Yamasani public void onStart() { 2854986044fd3bce877247e425374b47967775081a8Amith Yamasani super.onStart(); 2864986044fd3bce877247e425374b47967775081a8Amith Yamasani 2874986044fd3bce877247e425374b47967775081a8Amith Yamasani // Register a listener for configuration change events. 2884986044fd3bce877247e425374b47967775081a8Amith Yamasani IntentFilter filter = new IntentFilter(); 2894986044fd3bce877247e425374b47967775081a8Amith Yamasani filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 2904986044fd3bce877247e425374b47967775081a8Amith Yamasani getContext().registerReceiver(mConfChangeListener, filter); 2914986044fd3bce877247e425374b47967775081a8Amith Yamasani } 2924986044fd3bce877247e425374b47967775081a8Amith Yamasani 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The search dialog is being dismissed, so handle all of the local shutdown operations. 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This function is designed to be idempotent so that dismiss() can be safely called at any time 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (even if already closed) and more likely to really dump any memory. No leaks! 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onStop() { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onStop(); 302444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 3034986044fd3bce877247e425374b47967775081a8Amith Yamasani getContext().unregisterReceiver(mConfChangeListener); 3044986044fd3bce877247e425374b47967775081a8Amith Yamasani 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // dump extra memory we're hanging on to 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLaunchComponent = null; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAppSearchData = null; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSearchable = null; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUserQuery = null; 310875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 3111c6907515134c8a2e086d2eed4427f909d301935Mike LeBeau 3121c6907515134c8a2e086d2eed4427f909d301935Mike LeBeau /** 3131480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau * Sets the search dialog to the 'working' state, which shows a working spinner in the 3141480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau * right hand size of the text field. 3151480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau * 3161480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau * @param working true to show spinner, false to hide spinner 3171480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau */ 3181480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau public void setWorking(boolean working) { 319dfcbc046d7fcd74c8aacd9f26bd48084900d3b4aBryan Mawhinney mWorkingSpinner.setAlpha(working ? 255 : 0); 320dfcbc046d7fcd74c8aacd9f26bd48084900d3b4aBryan Mawhinney mWorkingSpinner.setVisible(working, false); 321dfcbc046d7fcd74c8aacd9f26bd48084900d3b4aBryan Mawhinney mWorkingSpinner.invalidateSelf(); 3221480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau } 323479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani 3241480eb27f5321ef5fc2faeee87c7464e279a4912Mike LeBeau /** 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Save the minimal set of data necessary to recreate the search 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 327444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * @return A bundle with the state of the dialog, or {@code null} if the search 328444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * dialog is not showing. 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Bundle onSaveInstanceState() { 332444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert if (!isShowing()) return null; 333444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bundle bundle = new Bundle(); 335444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // setup info so I can recreate this particular search 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData); 339b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); 340b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bundle; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Restore the state of the dialog from a previously saved bundle. 346875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param savedInstanceState The state of the dialog previously saved by 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onSaveInstanceState()}. 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onRestoreInstanceState(Bundle savedInstanceState) { 352444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert if (savedInstanceState == null) return; 353444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA); 356b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); 357b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert 358b0ae27f4e10a9e5fe56b9ca549718051fe342bbaBjorn Bringert // show the dialog. 359479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani if (!doShow(userQuery, false, launchComponent, appSearchData)) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // for some reason, we couldn't re-instantiate 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 364968ec938399033d280b1648123104ac567f2a093Amith Yamasani 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 366875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Called after resources have changed, e.g. after screen rotation or locale change. 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 368444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert public void onConfigurationChanged() { 369479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani if (mSearchable != null && isShowing()) { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Redraw (resources may have changed) 3711fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau updateSearchAppIcon(); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateSearchBadge(); 373d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani if (isLandscapeMode(getContext())) { 374d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani mSearchAutoComplete.ensureImeVisible(true); 375d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani } 376d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 378d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani 379d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani static boolean isLandscapeMode(Context context) { 380d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani return context.getResources().getConfiguration().orientation 381d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani == Configuration.ORIENTATION_LANDSCAPE; 382d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani } 383d25eb35b6b80b6f8065ab39b1cf1abb1fd801234Amith Yamasani 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 385875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Update the UI according to the info in the current value of {@link #mSearchable}. 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 387875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private void updateUI() { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSearchable != null) { 389ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen mDecor.setVisibility(View.VISIBLE); 390875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen updateSearchAutoComplete(); 3911fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau updateSearchAppIcon(); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateSearchBadge(); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // In order to properly configure the input method (if one is being used), we 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to let it know if we'll be providing suggestions. Although it would be 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // difficult/expensive to know if every last detail has been configured properly, we 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // can at least see if a suggestions provider has been configured, and use that 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // as our trigger. 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int inputType = mSearchable.getInputType(); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only touch this if the input type is set up for text (which it almost certainly 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // should be, in the case of search!) 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The existence of a suggestions authority is the proxy for "suggestions 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // are available here" 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSearchable.getSuggestAuthority() != null) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 410875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mSearchAutoComplete.setInputType(inputType); 411662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath mSearchAutoCompleteImeOptions = mSearchable.getImeOptions(); 412662df0b9630fd685a7cf86bbfec15ac6b6c286c6Satish Sampath mSearchAutoComplete.setImeOptions(mSearchAutoCompleteImeOptions); 4137df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau 4147df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau // If the search dialog is going to show a voice search button, then don't let 4157df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau // the soft keyboard display a microphone button if it would have otherwise. 4167df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau if (mSearchable.getVoiceSearchEnabled()) { 4177df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau mSearchAutoComplete.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); 4187df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau } else { 4197df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau mSearchAutoComplete.setPrivateImeOptions(null); 4207df846186d29ddfa4a567deddd04ad1043d32fd8Mike LeBeau } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 423875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 425875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Updates the auto-complete text view. 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 427875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private void updateSearchAutoComplete() { 4288d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert // we dismiss the entire dialog instead 4298d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert mSearchAutoComplete.setDropDownDismissedOnCompletion(false); 430968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchAutoComplete.setForceIgnoreOutsideTouch(false); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4331fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau private void updateSearchAppIcon() { 434968ec938399033d280b1648123104ac567f2a093Amith Yamasani PackageManager pm = getContext().getPackageManager(); 435968ec938399033d280b1648123104ac567f2a093Amith Yamasani Drawable icon; 436968ec938399033d280b1648123104ac567f2a093Amith Yamasani try { 437968ec938399033d280b1648123104ac567f2a093Amith Yamasani ActivityInfo info = pm.getActivityInfo(mLaunchComponent, 0); 438968ec938399033d280b1648123104ac567f2a093Amith Yamasani icon = pm.getApplicationIcon(info.applicationInfo); 439968ec938399033d280b1648123104ac567f2a093Amith Yamasani if (DBG) 440968ec938399033d280b1648123104ac567f2a093Amith Yamasani Log.d(LOG_TAG, "Using app-specific icon"); 441968ec938399033d280b1648123104ac567f2a093Amith Yamasani } catch (NameNotFoundException e) { 442968ec938399033d280b1648123104ac567f2a093Amith Yamasani icon = pm.getDefaultActivityIcon(); 443968ec938399033d280b1648123104ac567f2a093Amith Yamasani Log.w(LOG_TAG, mLaunchComponent + " not found, using generic app icon"); 4441fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau } 445968ec938399033d280b1648123104ac567f2a093Amith Yamasani mAppIcon.setImageDrawable(icon); 446968ec938399033d280b1648123104ac567f2a093Amith Yamasani mAppIcon.setVisibility(View.VISIBLE); 447968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL, mSearchPlate.getPaddingTop(), mSearchPlate.getPaddingRight(), mSearchPlate.getPaddingBottom()); 4481fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau } 4491fd73239dcd2f17603e0819ca9963e04c8267bb2Mike LeBeau 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 451875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Setup the search "Badge" if requested by mode flags. 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateSearchBadge() { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // assume both hidden 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int visibility = View.GONE; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable icon = null; 457875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen CharSequence text = null; 458968ec938399033d280b1648123104ac567f2a093Amith Yamasani 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // optionally show one or the other. 460a92041306e4d73baa10fb711fb905b9590f06b26Bjorn Bringert if (mSearchable.useBadgeIcon()) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project icon = mActivityContext.getResources().getDrawable(mSearchable.getIconId()); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project visibility = View.VISIBLE; 463875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (DBG) Log.d(LOG_TAG, "Using badge icon: " + mSearchable.getIconId()); 464a92041306e4d73baa10fb711fb905b9590f06b26Bjorn Bringert } else if (mSearchable.useBadgeLabel()) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = mActivityContext.getResources().getText(mSearchable.getLabelId()).toString(); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project visibility = View.VISIBLE; 467875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (DBG) Log.d(LOG_TAG, "Using badge label: " + mSearchable.getLabelId()); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469968ec938399033d280b1648123104ac567f2a093Amith Yamasani 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBadgeLabel.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBadgeLabel.setText(text); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBadgeLabel.setVisibility(visibility); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 475479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani /* 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Listeners of various types 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 480875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * {@link Dialog#onTouchEvent(MotionEvent)} will cancel the dialog only when the 481875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * touch is outside the window. But the window includes space for the drop-down, 482875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * so we also cancel on taps outside the search bar when the drop-down is not showing. 483875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 484875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen @Override 485875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public boolean onTouchEvent(MotionEvent event) { 486875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // cancel if the drop-down is not showing and the touch event was outside the search plate 487875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (!mSearchAutoComplete.isPopupShowing() && isOutOfBounds(mSearchPlate, event)) { 488875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (DBG) Log.d(LOG_TAG, "Pop-up not showing and outside of search plate."); 489875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen cancel(); 490875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return true; 491875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 492875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Let Dialog handle events outside the window while the pop-up is showing. 493875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return super.onTouchEvent(event); 494875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 495968ec938399033d280b1648123104ac567f2a093Amith Yamasani 496875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private boolean isOutOfBounds(View v, MotionEvent event) { 497875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen final int x = (int) event.getX(); 498875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen final int y = (int) event.getY(); 499875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); 500875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return (x < -slop) || (y < -slop) 501875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen || (x > (v.getWidth()+slop)) 502875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen || (y > (v.getHeight()+slop)); 503875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 505a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn @Override 506ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen public void hide() { 507444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert if (!isShowing()) return; 508444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 509a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn // We made sure the IME was displayed, so also make sure it is closed 510a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn // when we go away. 511a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn InputMethodManager imm = (InputMethodManager)getContext() 512a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn .getSystemService(Context.INPUT_METHOD_SERVICE); 513a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn if (imm != null) { 514a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn imm.hideSoftInputFromWindow( 515a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn getWindow().getDecorView().getWindowToken(), 0); 516a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn } 517ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen 518ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen super.hide(); 519a8f556ee8cee24674663fd73c7a5b5a919b2d5bbDianne Hackborn } 520875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 521875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 522875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Launch a search for the text in the query text field. 523875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 524968ec938399033d280b1648123104ac567f2a093Amith Yamasani public void launchQuerySearch() { 525875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); 526875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 529875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Launch a search for the text in the query text field. 530875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 531875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param actionKey The key code of the action key that was pressed, 532875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. 533875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param actionMsg The message for the action key that was pressed, 534875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or <code>null</code> if none. 535875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 536968ec938399033d280b1648123104ac567f2a093Amith Yamasani protected void launchQuerySearch(int actionKey, String actionMsg) { 537875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen String query = mSearchAutoComplete.getText().toString(); 538479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani String action = Intent.ACTION_SEARCH; 539968ec938399033d280b1648123104ac567f2a093Amith Yamasani Intent intent = createIntent(action, null, null, query, actionKey, actionMsg); 540875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen launchIntent(intent); 541875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 542a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen 543875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 544e9ce3f01d42769f03f10e70c3244500e92d7eee1Amith Yamasani * Launches an intent, including any special intent handling. 545875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 546875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private void launchIntent(Intent intent) { 547875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (intent == null) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 550ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen Log.d(LOG_TAG, "launching " + intent); 5514899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert try { 552479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // If the intent was created from a suggestion, it will always have an explicit 553479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // component here. 554479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani getContext().startActivity(intent); 555479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // If the search switches to a different activity, 556479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // SearchDialogWrapper#performActivityResuming 557479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // will handle hiding the dialog when the next activity starts, but for 558479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // real in-app search, we still need to dismiss the dialog. 559479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani dismiss(); 5604899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert } catch (RuntimeException ex) { 5614899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert Log.e(LOG_TAG, "Failed launch activity: " + intent, ex); 5624899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert } 5634899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert } 564876627d8c52300608c8c716f980a8686f43bf476Karl Rosaen 5654899e386ff9541e066a37cb5e9449844ded5ae4eBjorn Bringert /** 566ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau * Sets the list item selection in the AutoCompleteTextView's ListView. 567ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau */ 568ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau public void setListSelection(int index) { 569ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau mSearchAutoComplete.setListSelection(index); 570ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau } 571a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen 572ae9760b62c400e3e7009d4a7b85e9524a5cd44fcMike LeBeau /** 573875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Constructs an intent from the given information and the search dialog state. 574875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 575875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param action Intent action. 576875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param data Intent data, or <code>null</code>. 577875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>. 578bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath * @param query Intent query, or <code>null</code>. 579875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param actionKey The key code of the action key that was pressed, 580875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. 581875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param actionMsg The message for the action key that was pressed, 582875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or <code>null</code> if none. 583be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert * @param mode The search mode, one of the acceptable values for 584be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert * {@link SearchManager#SEARCH_MODE}, or {@code null}. 585875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @return The intent. 586875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 587bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath private Intent createIntent(String action, Uri data, String extraData, String query, 588e678f46ec45076203f6260f8a26f56d838c6b6ffAmith Yamasani int actionKey, String actionMsg) { 589875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Now build the Intent 590875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen Intent intent = new Intent(action); 5918d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 592442da48b24f75e6075763b89943b513197a0bfe9Bjorn Bringert // We need CLEAR_TOP to avoid reusing an old task that has other activities 593dc1396c881b80074c99d171aee02d3a5486180caEvan Millar // on top of the one we want. We don't want to do this in in-app search though, 594dc1396c881b80074c99d171aee02d3a5486180caEvan Millar // as it can be destructive to the activity stack. 595875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (data != null) { 596875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.setData(data); 597875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 5985f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert intent.putExtra(SearchManager.USER_QUERY, mUserQuery); 599875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (query != null) { 600875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.putExtra(SearchManager.QUERY, query); 601875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 602875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (extraData != null) { 603875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); 604875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 605875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (mAppSearchData != null) { 606875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.putExtra(SearchManager.APP_DATA, mAppSearchData); 607875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 608875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { 609875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.putExtra(SearchManager.ACTION_KEY, actionKey); 610875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen intent.putExtra(SearchManager.ACTION_MSG, actionMsg); 611875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 612479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani intent.setComponent(mSearchable.getSearchActivity()); 613875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return intent; 614875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 615479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani 616875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 617077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert * The root element in the search bar layout. This is a custom view just to override 618077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert * the handling of the back button. 619077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert */ 620077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert public static class SearchBar extends LinearLayout { 621077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 622077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert private SearchDialog mSearchDialog; 623077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 624077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert public SearchBar(Context context, AttributeSet attrs) { 625077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert super(context, attrs); 626077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert } 627077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 628077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert public SearchBar(Context context) { 629077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert super(context); 630077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert } 631077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 632077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert public void setSearchDialog(SearchDialog searchDialog) { 633077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert mSearchDialog = searchDialog; 634077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert } 635077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 636077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert /** 6378abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell * Don't allow action modes in a SearchBar, it looks silly. 6388abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell */ 6398abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell @Override 6408abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { 6418abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell return null; 6428abebcde3fd2317b25629263db6ad4637c8eeb34Adam Powell } 643077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert } 644077357ccf0c8b35094a69c3fc8bddd9ee605cf78Bjorn Bringert 645968ec938399033d280b1648123104ac567f2a093Amith Yamasani private boolean isEmpty(AutoCompleteTextView actv) { 646968ec938399033d280b1648123104ac567f2a093Amith Yamasani return TextUtils.getTrimmedLength(actv.getText()) == 0; 647875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 64887d61f22e13e81550559c92f6cf6fb795a39d37fBjorn Bringert 64987d61f22e13e81550559c92f6cf6fb795a39d37fBjorn Bringert @Override 65087d61f22e13e81550559c92f6cf6fb795a39d37fBjorn Bringert public void onBackPressed() { 651a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert // If the input method is covering the search dialog completely, 652a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert // e.g. in landscape mode with no hard keyboard, dismiss just the input method 653a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert InputMethodManager imm = (InputMethodManager)getContext() 654a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert .getSystemService(Context.INPUT_METHOD_SERVICE); 655a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert if (imm != null && imm.isFullscreenMode() && 656a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0)) { 657a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert return; 658a6309c30722ad3aee88ddc2394cea2a499168d99Bjorn Bringert } 659479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani // Close search dialog 660479ae0a28099eb77299fe0f44d4dfabce3115fb6Amith Yamasani cancel(); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 66287d61f22e13e81550559c92f6cf6fb795a39d37fBjorn Bringert 663968ec938399033d280b1648123104ac567f2a093Amith Yamasani private boolean onClosePressed() { 664968ec938399033d280b1648123104ac567f2a093Amith Yamasani // Dismiss the dialog if close button is pressed when there's no query text 665968ec938399033d280b1648123104ac567f2a093Amith Yamasani if (isEmpty(mSearchAutoComplete)) { 666968ec938399033d280b1648123104ac567f2a093Amith Yamasani dismiss(); 667968ec938399033d280b1648123104ac567f2a093Amith Yamasani return true; 668968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 669968ec938399033d280b1648123104ac567f2a093Amith Yamasani 670968ec938399033d280b1648123104ac567f2a093Amith Yamasani return false; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 672875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 673968ec938399033d280b1648123104ac567f2a093Amith Yamasani private final SearchView.OnCloseListener mOnCloseListener = new SearchView.OnCloseListener() { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 675968ec938399033d280b1648123104ac567f2a093Amith Yamasani public boolean onClose() { 676968ec938399033d280b1648123104ac567f2a093Amith Yamasani return onClosePressed(); 677968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 678968ec938399033d280b1648123104ac567f2a093Amith Yamasani }; 679968ec938399033d280b1648123104ac567f2a093Amith Yamasani 68001f21354654a315ea2a2a1668bbda50645123d4aAdam Powell private final SearchView.OnQueryTextListener mOnQueryChangeListener = 68101f21354654a315ea2a2a1668bbda50645123d4aAdam Powell new SearchView.OnQueryTextListener() { 682968ec938399033d280b1648123104ac567f2a093Amith Yamasani 68301f21354654a315ea2a2a1668bbda50645123d4aAdam Powell public boolean onQueryTextSubmit(String query) { 684968ec938399033d280b1648123104ac567f2a093Amith Yamasani dismiss(); 685968ec938399033d280b1648123104ac567f2a093Amith Yamasani return false; 686968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 687968ec938399033d280b1648123104ac567f2a093Amith Yamasani 68801f21354654a315ea2a2a1668bbda50645123d4aAdam Powell public boolean onQueryTextChange(String newText) { 689968ec938399033d280b1648123104ac567f2a093Amith Yamasani return false; 690968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 691968ec938399033d280b1648123104ac567f2a093Amith Yamasani }; 692968ec938399033d280b1648123104ac567f2a093Amith Yamasani 69301f21354654a315ea2a2a1668bbda50645123d4aAdam Powell private final SearchView.OnSuggestionListener mOnSuggestionSelectionListener = 69401f21354654a315ea2a2a1668bbda50645123d4aAdam Powell new SearchView.OnSuggestionListener() { 695968ec938399033d280b1648123104ac567f2a093Amith Yamasani 69601f21354654a315ea2a2a1668bbda50645123d4aAdam Powell public boolean onSuggestionSelect(int position) { 697968ec938399033d280b1648123104ac567f2a093Amith Yamasani return false; 698968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 699968ec938399033d280b1648123104ac567f2a093Amith Yamasani 70001f21354654a315ea2a2a1668bbda50645123d4aAdam Powell public boolean onSuggestionClick(int position) { 701968ec938399033d280b1648123104ac567f2a093Amith Yamasani dismiss(); 702968ec938399033d280b1648123104ac567f2a093Amith Yamasani return false; 703968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 704968ec938399033d280b1648123104ac567f2a093Amith Yamasani }; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 707968ec938399033d280b1648123104ac567f2a093Amith Yamasani * Sets the text in the query box, updating the suggestions. 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709968ec938399033d280b1648123104ac567f2a093Amith Yamasani private void setUserQuery(String query) { 710968ec938399033d280b1648123104ac567f2a093Amith Yamasani if (query == null) { 711968ec938399033d280b1648123104ac567f2a093Amith Yamasani query = ""; 712968ec938399033d280b1648123104ac567f2a093Amith Yamasani } 713968ec938399033d280b1648123104ac567f2a093Amith Yamasani mUserQuery = query; 714968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchAutoComplete.setText(query); 715968ec938399033d280b1648123104ac567f2a093Amith Yamasani mSearchAutoComplete.setSelection(query.length()); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 718