I am using the the SearchView
in the ActionBar
of the ListView
. The magnifying glass can be touched, the SearchView
shows its edit box, and the user can enter the text for filtering the content of the list. It almost works. However, when the user presses the Up button, the SearchView
collapses back to the icon, the text inside the widget is cleared, and the filtering is reset. The effect (in my case) is that the list can be filtered only when the SearchView
is not iconified. The wanted behaviour is to keep the filter text also after the SearchView
was collapsed.
Attention: The behaviour probably changed in Android 4.3. With 4.2.2 it worked as wanted. See the observations below.
Details: To be more specific, the menu contains the following item:
<item android:id="@+id/menu_search_customers"
android:title="@string/menu_search_text"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView" />
Notice the icon and the android:showAsAction
. I belive the Up button appears by default when the SearchView
is expanded (by Up I mean the <
plus the icon -- see the right image with the blue book from the official Navigation with Back and Up). It seems that the default handler implementation just collapses the expanded SearchView
(returns back to the icon state).
When debugging, I have found that the onQueryTextChange()
is fired with the empty text when the Up is used. (I believe this was not the case with Android 4.2.2, because it worked as wanted before the OS update.) This is the reason why the filtering of the list items is also reset -- see my onQueryTextChange()
below. I want the SearchView
collapsed, and the filter text displayed as subtitle in the action bar.
So far, my code related to the SearchView
looks like this:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater adds the magnifying glass icon for the SearchView
// to the ActionBar as the always visible menu item.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.customers_menu, menu);
// Get the related SearchView widget.
SearchView sv = (SearchView) menu.findItem(R.id.menu_search_customers)
.getActionView();
// Get the changes immediately.
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// I am not sure whether the onQueryTextSubmit() is important
// for the purpose.
@Override
public boolean onQueryTextSubmit(String query) {
getActionBar().setSubtitle(mCurFilter);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
// The newText is stored into a member variable that
// is used when the new CursorLoader is created.
mCurFilter = newText;
getActionBar().setSubtitle(mCurFilter);
getLoaderManager().restartLoader(0, null,
CustomersOverviewActivity.this);
return true;
}
});
return true;
}
The restarted loader calls the onCreateLoader
. Notice the mCurFilter
is used for building the SQL query:
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { CustomerTable._ID,
CustomerTable.CODE,
CustomerTable.NAME,
CustomerTable.STREET,
CustomerTable.TOWN };
String selection = null; // init
String[] selectionArgs = null; // init
if ( ! mCurFilter.isEmpty()) {
selection = CustomerTable.NAME + " like ?";
selectionArgs = new String[]{ "%" + mCurFilter +"%" };
}
CursorLoader cursorLoader = new CursorLoader(this,
DemoContentProvider.CUSTOMERS_CONTENT_URI, projection,
selection, selectionArgs,
orderInfo);
return cursorLoader;
}
I would like to detect the situation when the Up is pressed before the onQueryTextChange()
is called. This way (say) I could set a flag and block the mCurFilter
assignment by the emptied SearchView
content. Also, when the search icon is expanded again, I would like to initialize the text in the expanded SearchView
from the mCurFilter
before it is shown (i.e. the expanded view is preset with the filter text). How that can be done?
Update: The earlier implementation of the SearchView
had...
@Override
public void onActionViewCollapsed() {
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Now, it contains...
@Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Do you know what could be the reason for setting the query to the empty string? Should I override the new implementation by the old code? Or is there a better way?
Stateful SearchView
is to prevent the onQueryListener not to be invoked with empty string only when it is called when the action view is expanded/collapsed. You can notice that I remove the listener you passed and readd it later again. Take your time to go over my code. Meanwhile I'll improve it and remove the clutter. – Anesthesiology