|
|
|
|
@@ -45,7 +45,6 @@ import android.text.TextWatcher;
|
|
|
|
|
import android.text.style.ImageSpan;
|
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.util.TypedValue;
|
|
|
|
|
import android.view.CollapsibleActionView;
|
|
|
|
|
import android.view.KeyEvent;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
@@ -99,17 +98,21 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
*/
|
|
|
|
|
private static final String IME_OPTION_NO_MICROPHONE = "nm";
|
|
|
|
|
|
|
|
|
|
private final SearchAutoComplete mQueryTextView;
|
|
|
|
|
private final SearchAutoComplete mSearchSrcTextView;
|
|
|
|
|
private final View mSearchEditFrame;
|
|
|
|
|
private final View mSearchPlate;
|
|
|
|
|
private final View mSubmitArea;
|
|
|
|
|
private final ImageView mSearchButton;
|
|
|
|
|
private final ImageView mSubmitButton;
|
|
|
|
|
private final ImageView mGoButton;
|
|
|
|
|
private final ImageView mCloseButton;
|
|
|
|
|
private final ImageView mVoiceButton;
|
|
|
|
|
private final ImageView mSearchHintIcon;
|
|
|
|
|
private final View mDropDownAnchor;
|
|
|
|
|
private final int mSearchIconResId;
|
|
|
|
|
|
|
|
|
|
/** Icon optionally displayed when the SearchView is collapsed. */
|
|
|
|
|
private final ImageView mCollapsedIcon;
|
|
|
|
|
|
|
|
|
|
/** Drawable used as an EditText hint. */
|
|
|
|
|
private final Drawable mSearchHintIcon;
|
|
|
|
|
|
|
|
|
|
// Resources used by SuggestionsAdapter to display suggestions.
|
|
|
|
|
private final int mSuggestionRowLayout;
|
|
|
|
|
@@ -262,30 +265,38 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
attrs, R.styleable.SearchView, defStyleAttr, defStyleRes);
|
|
|
|
|
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
|
|
|
|
|
Context.LAYOUT_INFLATER_SERVICE);
|
|
|
|
|
final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, R.layout.search_view);
|
|
|
|
|
final int layoutResId = a.getResourceId(
|
|
|
|
|
R.styleable.SearchView_layout, R.layout.search_view);
|
|
|
|
|
inflater.inflate(layoutResId, this, true);
|
|
|
|
|
|
|
|
|
|
mQueryTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
|
|
|
|
|
mQueryTextView.setSearchView(this);
|
|
|
|
|
mSearchSrcTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
|
|
|
|
|
mSearchSrcTextView.setSearchView(this);
|
|
|
|
|
|
|
|
|
|
mSearchEditFrame = findViewById(R.id.search_edit_frame);
|
|
|
|
|
mSearchPlate = findViewById(R.id.search_plate);
|
|
|
|
|
mSubmitArea = findViewById(R.id.submit_area);
|
|
|
|
|
mSearchButton = (ImageView) findViewById(R.id.search_button);
|
|
|
|
|
mSubmitButton = (ImageView) findViewById(R.id.search_go_btn);
|
|
|
|
|
mGoButton = (ImageView) findViewById(R.id.search_go_btn);
|
|
|
|
|
mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
|
|
|
|
|
mVoiceButton = (ImageView) findViewById(R.id.search_voice_btn);
|
|
|
|
|
mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon);
|
|
|
|
|
mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);
|
|
|
|
|
|
|
|
|
|
// Set up icons and backgrounds.
|
|
|
|
|
mSearchPlate.setBackground(a.getDrawable(R.styleable.SearchView_queryBackground));
|
|
|
|
|
mSubmitArea.setBackground(a.getDrawable(R.styleable.SearchView_submitBackground));
|
|
|
|
|
mSearchIconResId = a.getResourceId(R.styleable.SearchView_searchIcon, 0);
|
|
|
|
|
mSearchButton.setImageResource(mSearchIconResId);
|
|
|
|
|
mSubmitButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_goIcon));
|
|
|
|
|
mSearchButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
|
|
|
|
|
mGoButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_goIcon));
|
|
|
|
|
mCloseButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_closeIcon));
|
|
|
|
|
mVoiceButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_voiceIcon));
|
|
|
|
|
mSearchHintIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
|
|
|
|
|
mCollapsedIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
|
|
|
|
|
|
|
|
|
|
// Prior to L MR1, the search hint icon defaulted to searchIcon. If the
|
|
|
|
|
// style does not have an explicit value set, fall back to that.
|
|
|
|
|
if (a.hasValueOrEmpty(R.styleable.SearchView_searchHintIcon)) {
|
|
|
|
|
mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchHintIcon);
|
|
|
|
|
} else {
|
|
|
|
|
mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchIcon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extract dropdown layout resource IDs for later use.
|
|
|
|
|
mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout,
|
|
|
|
|
@@ -294,18 +305,18 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
|
|
|
|
|
mSearchButton.setOnClickListener(mOnClickListener);
|
|
|
|
|
mCloseButton.setOnClickListener(mOnClickListener);
|
|
|
|
|
mSubmitButton.setOnClickListener(mOnClickListener);
|
|
|
|
|
mGoButton.setOnClickListener(mOnClickListener);
|
|
|
|
|
mVoiceButton.setOnClickListener(mOnClickListener);
|
|
|
|
|
mQueryTextView.setOnClickListener(mOnClickListener);
|
|
|
|
|
mSearchSrcTextView.setOnClickListener(mOnClickListener);
|
|
|
|
|
|
|
|
|
|
mQueryTextView.addTextChangedListener(mTextWatcher);
|
|
|
|
|
mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
|
|
|
|
|
mQueryTextView.setOnItemClickListener(mOnItemClickListener);
|
|
|
|
|
mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener);
|
|
|
|
|
mQueryTextView.setOnKeyListener(mTextKeyListener);
|
|
|
|
|
mSearchSrcTextView.addTextChangedListener(mTextWatcher);
|
|
|
|
|
mSearchSrcTextView.setOnEditorActionListener(mOnEditorActionListener);
|
|
|
|
|
mSearchSrcTextView.setOnItemClickListener(mOnItemClickListener);
|
|
|
|
|
mSearchSrcTextView.setOnItemSelectedListener(mOnItemSelectedListener);
|
|
|
|
|
mSearchSrcTextView.setOnKeyListener(mTextKeyListener);
|
|
|
|
|
|
|
|
|
|
// Inform any listener of focus changes
|
|
|
|
|
mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
|
|
|
|
|
mSearchSrcTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
|
|
|
|
|
|
|
|
|
|
public void onFocusChange(View v, boolean hasFocus) {
|
|
|
|
|
if (mOnQueryTextFocusChangeListener != null) {
|
|
|
|
|
@@ -350,7 +361,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
|
|
|
|
|
mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
|
|
|
|
|
|
|
|
mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor());
|
|
|
|
|
mDropDownAnchor = findViewById(mSearchSrcTextView.getDropDownAnchor());
|
|
|
|
|
if (mDropDownAnchor != null) {
|
|
|
|
|
mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() {
|
|
|
|
|
@Override
|
|
|
|
|
@@ -393,7 +404,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
if (mVoiceButtonEnabled) {
|
|
|
|
|
// Disable the microphone on the keyboard, as a mic is displayed near the text box
|
|
|
|
|
// TODO: use imeOptions to disable voice input when the new API will be available
|
|
|
|
|
mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
|
|
|
|
|
mSearchSrcTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
|
|
|
|
|
}
|
|
|
|
|
updateViewsVisibility(isIconified());
|
|
|
|
|
}
|
|
|
|
|
@@ -416,7 +427,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* @attr ref android.R.styleable#SearchView_imeOptions
|
|
|
|
|
*/
|
|
|
|
|
public void setImeOptions(int imeOptions) {
|
|
|
|
|
mQueryTextView.setImeOptions(imeOptions);
|
|
|
|
|
mSearchSrcTextView.setImeOptions(imeOptions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -427,7 +438,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* @attr ref android.R.styleable#SearchView_imeOptions
|
|
|
|
|
*/
|
|
|
|
|
public int getImeOptions() {
|
|
|
|
|
return mQueryTextView.getImeOptions();
|
|
|
|
|
return mSearchSrcTextView.getImeOptions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -439,7 +450,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* @attr ref android.R.styleable#SearchView_inputType
|
|
|
|
|
*/
|
|
|
|
|
public void setInputType(int inputType) {
|
|
|
|
|
mQueryTextView.setInputType(inputType);
|
|
|
|
|
mSearchSrcTextView.setInputType(inputType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -449,7 +460,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* @attr ref android.R.styleable#SearchView_inputType
|
|
|
|
|
*/
|
|
|
|
|
public int getInputType() {
|
|
|
|
|
return mQueryTextView.getInputType();
|
|
|
|
|
return mSearchSrcTextView.getInputType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @hide */
|
|
|
|
|
@@ -461,7 +472,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
if (!isFocusable()) return false;
|
|
|
|
|
// If it is not iconified, then give the focus to the text field
|
|
|
|
|
if (!isIconified()) {
|
|
|
|
|
boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
|
|
|
|
|
boolean result = mSearchSrcTextView.requestFocus(direction, previouslyFocusedRect);
|
|
|
|
|
if (result) {
|
|
|
|
|
updateViewsVisibility(false);
|
|
|
|
|
}
|
|
|
|
|
@@ -477,7 +488,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
mClearingFocus = true;
|
|
|
|
|
setImeVisibility(false);
|
|
|
|
|
super.clearFocus();
|
|
|
|
|
mQueryTextView.clearFocus();
|
|
|
|
|
mSearchSrcTextView.clearFocus();
|
|
|
|
|
mClearingFocus = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -536,7 +547,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* @return the query string
|
|
|
|
|
*/
|
|
|
|
|
public CharSequence getQuery() {
|
|
|
|
|
return mQueryTextView.getText();
|
|
|
|
|
return mSearchSrcTextView.getText();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -548,9 +559,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* text field.
|
|
|
|
|
*/
|
|
|
|
|
public void setQuery(CharSequence query, boolean submit) {
|
|
|
|
|
mQueryTextView.setText(query);
|
|
|
|
|
mSearchSrcTextView.setText(query);
|
|
|
|
|
if (query != null) {
|
|
|
|
|
mQueryTextView.setSelection(mQueryTextView.length());
|
|
|
|
|
mSearchSrcTextView.setSelection(mSearchSrcTextView.length());
|
|
|
|
|
mUserQuery = query;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -711,7 +722,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
public void setSuggestionsAdapter(CursorAdapter adapter) {
|
|
|
|
|
mSuggestionsAdapter = adapter;
|
|
|
|
|
|
|
|
|
|
mQueryTextView.setAdapter(mSuggestionsAdapter);
|
|
|
|
|
mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -789,12 +800,12 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
// Visibility of views that are visible when collapsed
|
|
|
|
|
final int visCollapsed = collapsed ? VISIBLE : GONE;
|
|
|
|
|
// Is there text in the query
|
|
|
|
|
final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
|
|
|
|
|
final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());
|
|
|
|
|
|
|
|
|
|
mSearchButton.setVisibility(visCollapsed);
|
|
|
|
|
updateSubmitButton(hasText);
|
|
|
|
|
mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
|
|
|
|
|
mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
|
|
|
|
|
mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
|
|
|
|
|
updateCloseButton();
|
|
|
|
|
updateVoiceButton(!hasText);
|
|
|
|
|
updateSubmitArea();
|
|
|
|
|
@@ -827,13 +838,13 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
&& (hasText || !mVoiceButtonEnabled)) {
|
|
|
|
|
visibility = VISIBLE;
|
|
|
|
|
}
|
|
|
|
|
mSubmitButton.setVisibility(visibility);
|
|
|
|
|
mGoButton.setVisibility(visibility);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateSubmitArea() {
|
|
|
|
|
int visibility = GONE;
|
|
|
|
|
if (isSubmitAreaEnabled()
|
|
|
|
|
&& (mSubmitButton.getVisibility() == VISIBLE
|
|
|
|
|
&& (mGoButton.getVisibility() == VISIBLE
|
|
|
|
|
|| mVoiceButton.getVisibility() == VISIBLE)) {
|
|
|
|
|
visibility = VISIBLE;
|
|
|
|
|
}
|
|
|
|
|
@@ -841,12 +852,15 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateCloseButton() {
|
|
|
|
|
final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
|
|
|
|
|
final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());
|
|
|
|
|
// Should we show the close button? It is not shown if there's no focus,
|
|
|
|
|
// field is not iconified by default and there is no text in it.
|
|
|
|
|
final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
|
|
|
|
|
mCloseButton.setVisibility(showClose ? VISIBLE : GONE);
|
|
|
|
|
mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
|
|
|
|
|
final Drawable closeButtonImg = mCloseButton.getDrawable();
|
|
|
|
|
if (closeButtonImg != null){
|
|
|
|
|
closeButtonImg.setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void postUpdateFocusedState() {
|
|
|
|
|
@@ -854,9 +868,16 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateFocusedState() {
|
|
|
|
|
boolean focused = mQueryTextView.hasFocus();
|
|
|
|
|
mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
|
|
|
|
|
mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
|
|
|
|
|
final boolean focused = mSearchSrcTextView.hasFocus();
|
|
|
|
|
final int[] stateSet = focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET;
|
|
|
|
|
final Drawable searchPlateBg = mSearchPlate.getBackground();
|
|
|
|
|
if (searchPlateBg != null) {
|
|
|
|
|
searchPlateBg.setState(stateSet);
|
|
|
|
|
}
|
|
|
|
|
final Drawable submitAreaBg = mSubmitArea.getBackground();
|
|
|
|
|
if (submitAreaBg != null) {
|
|
|
|
|
submitAreaBg.setState(stateSet);
|
|
|
|
|
}
|
|
|
|
|
invalidate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -896,11 +917,11 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
onSearchClicked();
|
|
|
|
|
} else if (v == mCloseButton) {
|
|
|
|
|
onCloseClicked();
|
|
|
|
|
} else if (v == mSubmitButton) {
|
|
|
|
|
} else if (v == mGoButton) {
|
|
|
|
|
onSubmitQuery();
|
|
|
|
|
} else if (v == mVoiceButton) {
|
|
|
|
|
onVoiceClicked();
|
|
|
|
|
} else if (v == mQueryTextView) {
|
|
|
|
|
} else if (v == mSearchSrcTextView) {
|
|
|
|
|
forceSuggestionQuery();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -925,7 +946,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
// entered query with the action key
|
|
|
|
|
SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
|
|
|
|
|
if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) {
|
|
|
|
|
launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView.getText()
|
|
|
|
|
launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mSearchSrcTextView.getText()
|
|
|
|
|
.toString());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
@@ -947,25 +968,25 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
|
|
|
|
|
if (DBG) {
|
|
|
|
|
Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + "), selection: "
|
|
|
|
|
+ mQueryTextView.getListSelection());
|
|
|
|
|
+ mSearchSrcTextView.getListSelection());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If a suggestion is selected, handle enter, search key, and action keys
|
|
|
|
|
// as presses on the selected suggestion
|
|
|
|
|
if (mQueryTextView.isPopupShowing()
|
|
|
|
|
&& mQueryTextView.getListSelection() != ListView.INVALID_POSITION) {
|
|
|
|
|
if (mSearchSrcTextView.isPopupShowing()
|
|
|
|
|
&& mSearchSrcTextView.getListSelection() != ListView.INVALID_POSITION) {
|
|
|
|
|
return onSuggestionsKey(v, keyCode, event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there is text in the query box, handle enter, and action keys
|
|
|
|
|
// The search key is handled by the dialog's onKeyDown().
|
|
|
|
|
if (!mQueryTextView.isEmpty() && event.hasNoModifiers()) {
|
|
|
|
|
if (!mSearchSrcTextView.isEmpty() && event.hasNoModifiers()) {
|
|
|
|
|
if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
|
|
|
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
|
|
|
|
v.cancelLongPress();
|
|
|
|
|
|
|
|
|
|
// Launch as a regular search.
|
|
|
|
|
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText()
|
|
|
|
|
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mSearchSrcTextView.getText()
|
|
|
|
|
.toString());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
@@ -973,7 +994,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
|
|
|
SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
|
|
|
|
|
if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) {
|
|
|
|
|
launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView
|
|
|
|
|
launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mSearchSrcTextView
|
|
|
|
|
.getText().toString());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
@@ -1001,7 +1022,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
// "click")
|
|
|
|
|
if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH
|
|
|
|
|
|| keyCode == KeyEvent.KEYCODE_TAB) {
|
|
|
|
|
int position = mQueryTextView.getListSelection();
|
|
|
|
|
int position = mSearchSrcTextView.getListSelection();
|
|
|
|
|
return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1012,18 +1033,18 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
// left key, at end if right key
|
|
|
|
|
// TODO: Reverse left/right for right-to-left languages, e.g.
|
|
|
|
|
// Arabic
|
|
|
|
|
int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView
|
|
|
|
|
int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mSearchSrcTextView
|
|
|
|
|
.length();
|
|
|
|
|
mQueryTextView.setSelection(selPoint);
|
|
|
|
|
mQueryTextView.setListSelection(0);
|
|
|
|
|
mQueryTextView.clearListSelection();
|
|
|
|
|
mQueryTextView.ensureImeVisible(true);
|
|
|
|
|
mSearchSrcTextView.setSelection(selPoint);
|
|
|
|
|
mSearchSrcTextView.setListSelection(0);
|
|
|
|
|
mSearchSrcTextView.clearListSelection();
|
|
|
|
|
mSearchSrcTextView.ensureImeVisible(true);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Next, check for an "up and out" move
|
|
|
|
|
if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection()) {
|
|
|
|
|
if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchSrcTextView.getListSelection()) {
|
|
|
|
|
// TODO: restoreUserQuery();
|
|
|
|
|
// let ACTV complete the move
|
|
|
|
|
return false;
|
|
|
|
|
@@ -1035,7 +1056,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
&& ((actionKey.getSuggestActionMsg() != null) || (actionKey
|
|
|
|
|
.getSuggestActionMsgColumn() != null))) {
|
|
|
|
|
// launch suggestion using action key column
|
|
|
|
|
int position = mQueryTextView.getListSelection();
|
|
|
|
|
int position = mSearchSrcTextView.getListSelection();
|
|
|
|
|
if (position != ListView.INVALID_POSITION) {
|
|
|
|
|
Cursor c = mSuggestionsAdapter.getCursor();
|
|
|
|
|
if (c.moveToPosition(position)) {
|
|
|
|
|
@@ -1078,24 +1099,24 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CharSequence getDecoratedHint(CharSequence hintText) {
|
|
|
|
|
// If the field is always expanded, then don't add the search icon to the hint
|
|
|
|
|
if (!mIconifiedByDefault) {
|
|
|
|
|
// If the field is always expanded or we don't have a search hint icon,
|
|
|
|
|
// then don't add the search icon to the hint.
|
|
|
|
|
if (!mIconifiedByDefault || mSearchHintIcon == null) {
|
|
|
|
|
return hintText;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final Drawable searchIcon = getContext().getDrawable(mSearchIconResId);
|
|
|
|
|
final int textSize = (int) (mQueryTextView.getTextSize() * 1.25);
|
|
|
|
|
searchIcon.setBounds(0, 0, textSize, textSize);
|
|
|
|
|
final int textSize = (int) (mSearchSrcTextView.getTextSize() * 1.25);
|
|
|
|
|
mSearchHintIcon.setBounds(0, 0, textSize, textSize);
|
|
|
|
|
|
|
|
|
|
final SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon
|
|
|
|
|
final SpannableStringBuilder ssb = new SpannableStringBuilder(" ");
|
|
|
|
|
ssb.setSpan(new ImageSpan(mSearchHintIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
|
|
|
ssb.append(hintText);
|
|
|
|
|
ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
|
|
|
return ssb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateQueryHint() {
|
|
|
|
|
if (mQueryHint != null) {
|
|
|
|
|
mQueryTextView.setHint(getDecoratedHint(mQueryHint));
|
|
|
|
|
mSearchSrcTextView.setHint(getDecoratedHint(mQueryHint));
|
|
|
|
|
} else if (mSearchable != null) {
|
|
|
|
|
CharSequence hint = null;
|
|
|
|
|
int hintId = mSearchable.getHintId();
|
|
|
|
|
@@ -1103,10 +1124,10 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
hint = getContext().getString(hintId);
|
|
|
|
|
}
|
|
|
|
|
if (hint != null) {
|
|
|
|
|
mQueryTextView.setHint(getDecoratedHint(hint));
|
|
|
|
|
mSearchSrcTextView.setHint(getDecoratedHint(hint));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
mQueryTextView.setHint(getDecoratedHint(""));
|
|
|
|
|
mSearchSrcTextView.setHint(getDecoratedHint(""));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1114,9 +1135,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* Updates the auto-complete text view.
|
|
|
|
|
*/
|
|
|
|
|
private void updateSearchAutoComplete() {
|
|
|
|
|
mQueryTextView.setDropDownAnimationStyle(0); // no animation
|
|
|
|
|
mQueryTextView.setThreshold(mSearchable.getSuggestThreshold());
|
|
|
|
|
mQueryTextView.setImeOptions(mSearchable.getImeOptions());
|
|
|
|
|
mSearchSrcTextView.setDropDownAnimationStyle(0); // no animation
|
|
|
|
|
mSearchSrcTextView.setThreshold(mSearchable.getSuggestThreshold());
|
|
|
|
|
mSearchSrcTextView.setImeOptions(mSearchable.getImeOptions());
|
|
|
|
|
int inputType = mSearchable.getInputType();
|
|
|
|
|
// We only touch this if the input type is set up for text (which it almost certainly
|
|
|
|
|
// should be, in the case of search!)
|
|
|
|
|
@@ -1135,7 +1156,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mQueryTextView.setInputType(inputType);
|
|
|
|
|
mSearchSrcTextView.setInputType(inputType);
|
|
|
|
|
if (mSuggestionsAdapter != null) {
|
|
|
|
|
mSuggestionsAdapter.changeCursor(null);
|
|
|
|
|
}
|
|
|
|
|
@@ -1144,7 +1165,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
if (mSearchable.getSuggestAuthority() != null) {
|
|
|
|
|
mSuggestionsAdapter = new SuggestionsAdapter(getContext(),
|
|
|
|
|
this, mSearchable, mOutsideDrawablesCache);
|
|
|
|
|
mQueryTextView.setAdapter(mSuggestionsAdapter);
|
|
|
|
|
mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
|
|
|
|
|
((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
|
|
|
|
|
mQueryRefinement ? SuggestionsAdapter.REFINE_ALL
|
|
|
|
|
: SuggestionsAdapter.REFINE_BY_ENTRY);
|
|
|
|
|
@@ -1161,7 +1182,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
int visibility = GONE;
|
|
|
|
|
if (mVoiceButtonEnabled && !isIconified() && empty) {
|
|
|
|
|
visibility = VISIBLE;
|
|
|
|
|
mSubmitButton.setVisibility(GONE);
|
|
|
|
|
mGoButton.setVisibility(GONE);
|
|
|
|
|
}
|
|
|
|
|
mVoiceButton.setVisibility(visibility);
|
|
|
|
|
}
|
|
|
|
|
@@ -1178,7 +1199,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private void onTextChanged(CharSequence newText) {
|
|
|
|
|
CharSequence text = mQueryTextView.getText();
|
|
|
|
|
CharSequence text = mSearchSrcTextView.getText();
|
|
|
|
|
mUserQuery = text;
|
|
|
|
|
boolean hasText = !TextUtils.isEmpty(text);
|
|
|
|
|
updateSubmitButton(hasText);
|
|
|
|
|
@@ -1192,7 +1213,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onSubmitQuery() {
|
|
|
|
|
CharSequence query = mQueryTextView.getText();
|
|
|
|
|
CharSequence query = mSearchSrcTextView.getText();
|
|
|
|
|
if (query != null && TextUtils.getTrimmedLength(query) > 0) {
|
|
|
|
|
if (mOnQueryChangeListener == null
|
|
|
|
|
|| !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
|
|
|
|
|
@@ -1206,11 +1227,11 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void dismissSuggestions() {
|
|
|
|
|
mQueryTextView.dismissDropDown();
|
|
|
|
|
mSearchSrcTextView.dismissDropDown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onCloseClicked() {
|
|
|
|
|
CharSequence text = mQueryTextView.getText();
|
|
|
|
|
CharSequence text = mSearchSrcTextView.getText();
|
|
|
|
|
if (TextUtils.isEmpty(text)) {
|
|
|
|
|
if (mIconifiedByDefault) {
|
|
|
|
|
// If the app doesn't override the close behavior
|
|
|
|
|
@@ -1222,8 +1243,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
mQueryTextView.setText("");
|
|
|
|
|
mQueryTextView.requestFocus();
|
|
|
|
|
mSearchSrcTextView.setText("");
|
|
|
|
|
mSearchSrcTextView.requestFocus();
|
|
|
|
|
setImeVisibility(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1231,7 +1252,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
|
|
|
|
|
private void onSearchClicked() {
|
|
|
|
|
updateViewsVisibility(false);
|
|
|
|
|
mQueryTextView.requestFocus();
|
|
|
|
|
mSearchSrcTextView.requestFocus();
|
|
|
|
|
setImeVisibility(true);
|
|
|
|
|
if (mOnSearchClickListener != null) {
|
|
|
|
|
mOnSearchClickListener.onClick(this);
|
|
|
|
|
@@ -1266,7 +1287,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
// Delayed update to make sure that the focus has settled down and window focus changes
|
|
|
|
|
// don't affect it. A synchronous update was not working.
|
|
|
|
|
postUpdateFocusedState();
|
|
|
|
|
if (mQueryTextView.hasFocus()) {
|
|
|
|
|
if (mSearchSrcTextView.hasFocus()) {
|
|
|
|
|
forceSuggestionQuery();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1286,7 +1307,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
setQuery("", false);
|
|
|
|
|
clearFocus();
|
|
|
|
|
updateViewsVisibility(true);
|
|
|
|
|
mQueryTextView.setImeOptions(mCollapsedImeOptions);
|
|
|
|
|
mSearchSrcTextView.setImeOptions(mCollapsedImeOptions);
|
|
|
|
|
mExpandedInActionView = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1298,9 +1319,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
if (mExpandedInActionView) return;
|
|
|
|
|
|
|
|
|
|
mExpandedInActionView = true;
|
|
|
|
|
mCollapsedImeOptions = mQueryTextView.getImeOptions();
|
|
|
|
|
mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
|
|
|
|
|
mQueryTextView.setText("");
|
|
|
|
|
mCollapsedImeOptions = mSearchSrcTextView.getImeOptions();
|
|
|
|
|
mSearchSrcTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
|
|
|
|
|
mSearchSrcTextView.setText("");
|
|
|
|
|
setIconified(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1326,17 +1347,17 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
|
|
|
|
|
+ res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
|
|
|
|
|
: 0;
|
|
|
|
|
mQueryTextView.getDropDownBackground().getPadding(dropDownPadding);
|
|
|
|
|
mSearchSrcTextView.getDropDownBackground().getPadding(dropDownPadding);
|
|
|
|
|
int offset;
|
|
|
|
|
if (isLayoutRtl) {
|
|
|
|
|
offset = - dropDownPadding.left;
|
|
|
|
|
} else {
|
|
|
|
|
offset = anchorPadding - (dropDownPadding.left + iconOffset);
|
|
|
|
|
}
|
|
|
|
|
mQueryTextView.setDropDownHorizontalOffset(offset);
|
|
|
|
|
mSearchSrcTextView.setDropDownHorizontalOffset(offset);
|
|
|
|
|
final int width = mDropDownAnchor.getWidth() + dropDownPadding.left
|
|
|
|
|
+ dropDownPadding.right + iconOffset - anchorPadding;
|
|
|
|
|
mQueryTextView.setDropDownWidth(width);
|
|
|
|
|
mSearchSrcTextView.setDropDownWidth(width);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1394,7 +1415,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* Query rewriting.
|
|
|
|
|
*/
|
|
|
|
|
private void rewriteQueryFromSuggestion(int position) {
|
|
|
|
|
CharSequence oldQuery = mQueryTextView.getText();
|
|
|
|
|
CharSequence oldQuery = mSearchSrcTextView.getText();
|
|
|
|
|
Cursor c = mSuggestionsAdapter.getCursor();
|
|
|
|
|
if (c == null) {
|
|
|
|
|
return;
|
|
|
|
|
@@ -1460,9 +1481,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
* Sets the text in the query box, without updating the suggestions.
|
|
|
|
|
*/
|
|
|
|
|
private void setQuery(CharSequence query) {
|
|
|
|
|
mQueryTextView.setText(query, true);
|
|
|
|
|
mSearchSrcTextView.setText(query, true);
|
|
|
|
|
// Move the cursor to the end
|
|
|
|
|
mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
|
|
|
|
|
mSearchSrcTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void launchQuerySearch(int actionKey, String actionMsg, String query) {
|
|
|
|
|
@@ -1648,8 +1669,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void forceSuggestionQuery() {
|
|
|
|
|
mQueryTextView.doBeforeTextChanged();
|
|
|
|
|
mQueryTextView.doAfterTextChanged();
|
|
|
|
|
mSearchSrcTextView.doBeforeTextChanged();
|
|
|
|
|
mSearchSrcTextView.doAfterTextChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static boolean isLandscapeMode(Context context) {
|
|
|
|
|
|