I am using Android 4.1.2. I have a SearchView widget on an ActionBar
. Documentation on SearchView.OnQueryTextListener
from the android developer site states that onQueryTextSubmit
is fired when "Called when the user submits the query. This could be due to a key press on the keyboard or due to pressing a submit button."
This does not happen if the search query is empty. I need this to fire on an empty query to clear the search filter of a ListView. Is this a bug or am I doing something wrong?
It is not a bug, the source code deliberately checks against null and empty values:
private void onSubmitQuery() {
CharSequence query = mQueryTextView.getText();
if (query != null && TextUtils.getTrimmedLength(query) > 0) {
However you should be able to use the OnQueryTextChange callback to clear your ListView's filterables when the user clears the search EditText.
ive an easier work around: use onQueryTextChange, but only render if its empty.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
renderList(true);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (searchView.getQuery().length() == 0) {
renderList(true);
}
return false;
}
});
I had the same problem and end up with the following solution: custom SearchView
+ OnQueryTextListener.onQueryTextChange
Custom SearchView:
public class MySearchView extends SearchView {
private boolean expanded;
public MySearchView(Context context) {
super(context);
}
@Override
public void onActionViewExpanded() {
super.onActionViewExpanded();
expanded = true;
}
@Override
public void onActionViewCollapsed() {
super.onActionViewCollapsed();
expanded = false;
}
public boolean isExpanded() {
return expanded;
}
}
Creating action and setting callback:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
searchAction = menu.add(0, SEARCH_ACTION_ID, 0 , getString(R.string.action_search));
searchAction.setShowAsAction(SHOW_AS_ACTION_ALWAYS | SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
searchView = new MySearchView(getSherlockActivity());
searchView.setOnQueryTextListener(searchQueryListener);
searchView.setIconifiedByDefault(true);
searchAction.setActionView(searchView);
}
And last the listener:
private OnQueryTextListener searchQueryListener = new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
search(query);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
if (searchView.isExpanded() && TextUtils.isEmpty(newText)) {
search("");
}
return true;
}
public void search(String query) {
// reset loader, swap cursor, etc.
}
};
Tested on ABS 4.3.
I had same issue with SearchView. My solution which consists of styling SearchView as shown in guide http://novoda.com/blog/styling-the-actionbar-searchview/ and setting OnEditorActionListener for EditText( How do I trigger an action when the user has hit enter?) which is part of the SearchView was this:
final SearchView searchView = (SearchView)findViewById(R.id.search);
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
EditText searchPlate = (EditText) searchView.findViewById(searchPlateId);
searchPlate.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
//Do something
}
return false;
}});
As others have mentioned this behavior is intentional. I gave up on a solution for OnQueryChangeListener
and decided to workaround by implementing OnEditorActionListener
on the SearchView's EditText
, which you can get a handle to using R.id.search_src_text
. As long as you setImeOptions
of the SearchView to EditorInfo.IME_ACTION_SEARCH
you can handle a click on the keyboard search button. See this SO answer for more details.
I had the same problem, since empty query's are not supported I had to download and use ActionBarSherlock and then modify the onSubmitQuery() method.
This is how my onSubmitQuery() looks like now
private void onSubmitQuery() {
CharSequence query = mQueryTextView.getText();
if (query == null) {query = "";}
if (mOnQueryChangeListener == null
|| !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
if (mSearchable != null) {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
setImeVisibility(false);
}
dismissSuggestions();
}
}
Hope this helps.
This is a very dirty hack, however it works correctly as expected, enabling the submit action even when there is no text entered (or entered then edited) in the SearchView.
It reflectively gains access to the inner TextView editor action listener, wraps it in a custom listener where it delegates the call to the handler, and finally sets it as the action listener of the inner TextView.
Class klass = searchView.getClass();
try {
Field currentListenerField = klass.getDeclaredField("mOnEditorActionListener");
currentListenerField.setAccessible(true);
TextView.OnEditorActionListener previousListener = (TextView.OnEditorActionListener) currentListenerField.get(searchView);
TextView.OnEditorActionListener newListener = new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (v.getText().length() == 0)
handleQuery("");
return previousListener.onEditorAction(v, actionId, event);
}
};
Field innerTextViewField = klass.getDeclaredField("mSearchSrcTextView");
innerTextViewField.setAccessible(true);
SearchView.SearchAutoComplete innerTextView = (SearchView.SearchAutoComplete) innerTextViewField.get(searchView);
innerTextView.setOnEditorActionListener(newListener);
} catch (Exception e) {
throw new IllegalStateException(e);
}
You cannot overwrite this behavior. A workaround could be to clear the filter, when a user exits the searchview.
You could use the OnCloseListener for this. However, this can cause problems as well, depending on the minimum API Level you are developing for.
Another option is to trigger the onQueryTextChange method manually through a TextWatcher:
public class MyActivity extends Activity implements SearchView.OnQueryTextListener, TextWatcher {
// Basic onCreate(Bundle) here
@Override
public boolean onCreateOptionsMenu (final Menu menu) {
getMenuInflater().inflate(R.menu.myMenu, menu);
final SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
final SearchManager manager = (SearchManager) getSystemService(SEARCH_SERVICE);
searchView.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(this);
final int resource_edit_text = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
((EditText) searchView.findViewById(resource_edit_text)).addTextChangedListener(this);
return super.onCreateOptionsMenu(menu);
}
// Implementation of TextWatcher, used to have a proper onQueryTextChange (it doesn't update when the last character is removed)
@Override
public void beforeTextChanged (final CharSequence charSequence, final int start, final int count, final int after) {}
@Override
public void onTextChanged (final CharSequence charSequence, final int start, final int before, final int after) {}
@Override
public void afterTextChanged (final Editable editable) {
if (editable.length() == 0)
onQueryTextChange(editable.toString());
}
// Implementation of OnQueryTextChangeListener
@Override
public boolean onQueryTextChange (final String query) {
// do stuff
return false;
}
@Override
public boolean onQueryTextSubmit (final String query) {
// do stuff
return false;
}
}
This all goes with all the default xml files which have been given up here, that is not the point of this answer. This is a workaround that I choose to use, feel free to use others
I can manage to do it simply by implementing the setOnQueryTextListener in this way:
SearchView searchView = (SearchView) menu.findItem(R.id.searchProductView).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
loadLocalData(newText);
}
return true;
}
});
Where my loadLocalData method is
//query my DB
products = ProductDAO.findByIdList(idList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
listView.setLayoutManager(layoutManager);
listView.setAdapter(<YOURADAPTER>)
This solution clears your query even if you clear the text with the "X" button
In my case I just wanted to enable user to clear his query as it was used as keyword in API search, so the simplest idea was:
searchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
userQuery = "";
}
});
where userQuery is my variable used for searching etc.
Hope it helps someone :)
It's an old thread but I've found another solution (Kotlin code, but works in Java as well):
override fun onQueryTextChange(newText: String?): Boolean {
if(newText == null || newText.isEmpty())
searchView.setQuery("\u00A0", false)
return true
}
\u00A0
is a character that looks like space, but code-wise it is not. In other words SearchView is not empty. Empty string or " "
would not work, because base SearchView uses trim, plus user may want to search text ending or beginning with space. But as far as I know users cannot enter \u00A0
character.
Then all you need to do is override getQuery to return super.getQuery.replace("\u00A0", "")
in your custom SearchView
来源:https://stackoverflow.com/questions/13576283/android-searchview-onquerytextlistener-onquerytextsubmit-not-fired-on-empty-quer