summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Amith Yamasani <yamasani@google.com> 2010-10-08 13:52:38 -0700
committer Amith Yamasani <yamasani@google.com> 2010-10-08 15:49:37 -0700
commit0594476ffa39481063cf7f1546ccfce509f02c65 (patch)
tree4ce8ceb3c5a5f6b6f5972ce00a1036bea6358368
parent9568a5ab2e51428685904a2d1fd18b4ec736ba0b (diff)
SearchView: Add some more listeners, IME dismiss improvements and focus control.
Addresses following bugs: 3067611 : Submit button incorrectly displayed 3064371 : Callback to report suggestion click 3008580 : Setting initial focus The SearchView will take initial focus now, reverting an earlier change. If you don't want it to take initial focus, then you must requestFocus on a different view on launching the activity, since the initial focus is desirable in other cases. This is normal behavior for all EditText widgets and SearchView shouldn't have a different behavior.
-rw-r--r--api/current.xml62
-rw-r--r--core/java/android/widget/SearchView.java139
2 files changed, 171 insertions, 30 deletions
diff --git a/api/current.xml b/api/current.xml
index 133647223d6e..35c0dc623b83 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -236406,6 +236406,32 @@
<parameter name="listener" type="android.widget.SearchView.OnQueryChangeListener">
</parameter>
</method>
+<method name="setOnQueryTextFocusChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.view.View.OnFocusChangeListener">
+</parameter>
+</method>
+<method name="setOnSuggestionSelectionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.SearchView.OnSuggestionSelectionListener">
+</parameter>
+</method>
<method name="setQuery"
return="void"
abstract="false"
@@ -236540,6 +236566,40 @@
</parameter>
</method>
</interface>
+<interface name="SearchView.OnSuggestionSelectionListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSuggestionClicked"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="onSuggestionSelected"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+</interface>
<interface name="SectionIndexer"
abstract="true"
static="false"
@@ -242818,7 +242878,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index dd67197c2aed..cfd6754cc439 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -56,6 +56,8 @@ public class SearchView extends LinearLayout {
private OnQueryChangeListener mOnQueryChangeListener;
private OnCloseListener mOnCloseListener;
+ private OnFocusChangeListener mOnQueryTextFocusChangeListener;
+ private OnSuggestionSelectionListener mOnSuggestionListener;
private boolean mIconifiedByDefault;
private boolean mIconified;
@@ -68,6 +70,7 @@ public class SearchView extends LinearLayout {
private boolean mSubmitButtonEnabled;
private CharSequence mQueryHint;
private boolean mQueryRefinement;
+ private boolean mClearingFocus;
private SearchableInfo mSearchable;
@@ -117,6 +120,32 @@ public class SearchView extends LinearLayout {
boolean onClose();
}
+ /**
+ * Callback interface for selection events on suggestions. These callbacks
+ * are only relevant when a SearchableInfo has been specified by {@link #setSearchableInfo}.
+ */
+ public interface OnSuggestionSelectionListener {
+
+ /**
+ * Called when a suggestion was selected by navigating to it.
+ * @param position the absolute position in the list of suggestions.
+ *
+ * @return true if the listener handles the event and wants to override the default
+ * behavior of possibly rewriting the query based on the selected item, false otherwise.
+ */
+ boolean onSuggestionSelected(int position);
+
+ /**
+ * Called when a suggestion was clicked.
+ * @param position the absolute position of the clicked item in the list of suggestions.
+ *
+ * @return true if the listener handles the event and wants to override the default
+ * behavior of launching any intent or submitting a search query specified on that item.
+ * Return false otherwise.
+ */
+ boolean onSuggestionClicked(int position);
+ }
+
public SearchView(Context context) {
this(context, null);
}
@@ -141,6 +170,15 @@ public class SearchView extends LinearLayout {
mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
mQueryTextView.setOnItemClickListener(mOnItemClickListener);
mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener);
+ // Inform any listener of focus changes
+ mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
+
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (mOnQueryTextFocusChangeListener != null) {
+ mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus);
+ }
+ }
+ });
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SearchView, 0, 0);
setIconifiedByDefault(a.getBoolean(R.styleable.SearchView_iconifiedByDefault, true));
@@ -165,6 +203,27 @@ public class SearchView extends LinearLayout {
updateViewsVisibility(mIconifiedByDefault);
}
+ /** @hide */
+ @Override
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+ if (mClearingFocus) return false;
+ boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
+ if (result && !isIconified()) {
+ setImeVisibility(true);
+ }
+ return result;
+ }
+
+ /** @hide */
+ @Override
+ public void clearFocus() {
+ mClearingFocus = true;
+ super.clearFocus();
+ mQueryTextView.clearFocus();
+ setImeVisibility(false);
+ mClearingFocus = false;
+ }
+
/**
* Sets a listener for user actions within the SearchView.
*
@@ -185,6 +244,24 @@ public class SearchView extends LinearLayout {
}
/**
+ * Sets a listener to inform when the focus of the query text field changes.
+ *
+ * @param listener the listener to inform of focus changes.
+ */
+ public void setOnQueryTextFocusChangeListener(OnFocusChangeListener listener) {
+ mOnQueryTextFocusChangeListener = listener;
+ }
+
+ /**
+ * Sets a listener to inform when a suggestion is focused or clicked.
+ *
+ * @param listener the listener to inform of suggestion selection events.
+ */
+ public void setOnSuggestionSelectionListener(OnSuggestionSelectionListener listener) {
+ mOnSuggestionListener = listener;
+ }
+
+ /**
* Sets a query string in the text field and optionally submits the query as well.
*
* @param query the query string. This replaces any query text already present in the
@@ -224,6 +301,7 @@ public class SearchView extends LinearLayout {
public void setIconifiedByDefault(boolean iconified) {
mIconifiedByDefault = iconified;
updateViewsVisibility(iconified);
+ setImeVisibility(!iconified);
}
/**
@@ -340,28 +418,25 @@ public class SearchView extends LinearLayout {
final int visCollapsed = collapsed ? VISIBLE : GONE;
// Visibility of views that are visible when expanded
final int visExpanded = collapsed ? GONE : VISIBLE;
+ // Is there text in the query
+ final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
mSearchButton.setVisibility(visCollapsed);
- mSubmitButton.setVisibility(mSubmitButtonEnabled ? visExpanded : GONE);
+ mSubmitButton.setVisibility(mSubmitButtonEnabled && hasText ? visExpanded : GONE);
mSearchEditFrame.setVisibility(visExpanded);
-
- setImeVisibility(!collapsed);
}
private void setImeVisibility(boolean visible) {
- // don't mess with the soft input if we're not iconified by default
- if (mIconifiedByDefault) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-
- // We made sure the IME was displayed, so also make sure it is closed
- // when we go away.
- if (imm != null) {
- if (visible) {
- imm.showSoftInputUnchecked(0, null);
- } else {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ // We made sure the IME was displayed, so also make sure it is closed
+ // when we go away.
+ if (imm != null) {
+ if (visible) {
+ imm.showSoftInputUnchecked(0, null);
+ } else {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
}
}
@@ -478,6 +553,7 @@ public class SearchView extends LinearLayout {
|| !mOnQueryChangeListener.onSubmitQuery(query.toString())) {
if (mSearchable != null) {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
+ setImeVisibility(false);
}
}
}
@@ -485,7 +561,14 @@ public class SearchView extends LinearLayout {
private void onCloseClicked() {
if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
- mQueryTextView.setText("");
+ CharSequence text = mQueryTextView.getText();
+ if (TextUtils.isEmpty(text)) {
+ // query field already empty, hide the keyboard and remove focus
+ mQueryTextView.clearFocus();
+ setImeVisibility(false);
+ } else {
+ mQueryTextView.setText("");
+ }
updateViewsVisibility(mIconifiedByDefault);
}
}
@@ -493,6 +576,7 @@ public class SearchView extends LinearLayout {
private void onSearchClicked() {
mQueryTextView.requestFocus();
updateViewsVisibility(false);
+ setImeVisibility(true);
}
private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
@@ -503,7 +587,10 @@ public class SearchView extends LinearLayout {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (DBG)
Log.d(LOG_TAG, "onItemClick() position " + position);
- launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
+ if (mOnSuggestionListener == null
+ || !mOnSuggestionListener.onSuggestionClicked(position)) {
+ launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
+ }
}
};
@@ -517,7 +604,10 @@ public class SearchView extends LinearLayout {
Log.d(LOG_TAG, "onItemSelected() position " + position);
// A suggestion has been selected, rewrite the query if possible,
// otherwise the restore the original query.
- rewriteQueryFromSuggestion(position);
+ if (mOnSuggestionListener == null
+ || !mOnSuggestionListener.onSuggestionSelected(position)) {
+ rewriteQueryFromSuggestion(position);
+ }
}
/**
@@ -722,13 +812,4 @@ public class SearchView extends LinearLayout {
public void afterTextChanged(Editable s) {
}
};
-
- /*
- * Avoid getting focus when searching for something to focus on.
- * The user will have to touch the text view to get focus.
- */
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
- return false;
- }
- }
+}