I am using Android 4.1.2. I have a SearchView
widget on an ActionBar
. Documentation on SearchView.OnQueryTextListener
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);
}
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
This is a complete example written in Kotlin:
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.appcompat.widget.SearchView
/**
* Custom [SearchView] which can listen to empty submit events
*
* If the internal implementation would change, this will not crash at runtime. It will simply
* ignore the empty submit listener and will continue to work as this is the base [SearchView]
*/
class EmptySubmitSearchView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : SearchView(context, attrs, defStyleAttr) {
private lateinit var searchAutoComplete: SearchAutoComplete
private lateinit var internalEditorListener: TextView.OnEditorActionListener
private var emptySubmitListener: OnEmptySubmitListener? = null
init {
try {
val defaultListenerField = SearchView::class.java
.getDeclaredField("mOnEditorActionListener")
defaultListenerField.isAccessible = true
internalEditorListener = defaultListenerField.get(this) as TextView.OnEditorActionListener
val searchAutoCompleteField = SearchView::class.java
.getDeclaredField("mSearchSrcTextView")
searchAutoCompleteField.isAccessible = true
searchAutoComplete = searchAutoCompleteField.get(this) as SearchAutoComplete
searchAutoComplete.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE && TextUtils.isEmpty(searchAutoComplete.text)) {
emptySubmitListener?.onEmptyTextSubmit()
} else {
internalEditorListener.onEditorAction(v, actionId, event)
}
true
}
} catch (ignored: Exception) {
//Some internal field has changed. Check there is a field called
//mSearchSrcTextView and mOnEditorActionListener and if not update them accordingly
}
}
/**
* Set custom empty listener or null to remove it
*/
fun setOnEmptySubmitListener(listener: OnEmptySubmitListener?) {
emptySubmitListener = listener
}
interface OnEmptySubmitListener {
fun onEmptyTextSubmit()
}
}
You can set a custom listener with setOnEmptySubmitListener
which will enable you to distinguish between events.
You can customize the actionId to respond to, in this case I had in my XML the EmptySubmitSearchView with this android:imeOptions="actionDone|flagNoExtractUi"
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.
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;
}});
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.