Reputation: 299
Short: When I click on my SearchViewIcon, the SearchView doesn't collapse/expand.
Long:
I"m using a SearchView to filter a RecyclerView in a Fragment that is in my MainActivity.
When I click on the SearchViewIcon (SearchView is iconified by default). I open the tab with the correct Fragment with this code:
searchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewPager.setCurrentItem(2, false);
}
});
The Tab with the correct Fragment is opened like expected. Also the text input is shown, but the SearchView stays iconified. (See picture below.)
My SearchView in XML:
<item
android:id="@+id/action_search"
android:orderInCategory="1"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/menu_item_search_title"
app:showAsAction="ifRoom"
app:queryHint="Search name or function"
app:actionViewClass="android.support.v7.widget.SearchView" />
Things I already tried:
Setting my showAsAction to always or ifRoom|collapseActionView
app:showAsAction="always"
app:showAsAction="ifRoom|collapseActionView"
Request focus on my SearchView:
searchView.requestFocus();
Expanding my SearchViewItem:
MenuItem searchViewItem = menu.findItem(R.id.action_search);
searchViewItem.expandActionView();
But non of these things worked...
EDIT Like the title says, if I click the SearchViewIcon again, the SearchView does expand.
Upvotes: 9
Views: 2558
Reputation: 412
Thanks to the upvoted answer above, this is what I did
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.contacts_menu, menu)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchItem = menu.findItem(R.id.action_search)
val searchView = searchItem.actionView as SearchView
searchView.queryHint = "Search contacts"
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
searchView.isIconifiedByDefault = false
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
Handler(Looper.getMainLooper()).post {
searchView.requestFocus()
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(searchView.findFocus(), 0)
}
return true
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
// Can choose to hide keyboard here
adapter.submitList(originalList)
binding.recyclerView.scrollToPosition(0)
return true
}
})
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
filterContacts(newText.orEmpty())
return true
}
})
return true
}
Upvotes: 0
Reputation: 3908
The simplest solution is to use always
option for app:showAsAction
:
app:showAsAction="always"
<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="search"
app:showAsAction="always"
app:actionViewClass="android.widget.SearchView"
/>
Upvotes: 1
Reputation: 1937
I've also encountered a similar problem, and was able to solve it. The main problems I've needed to solve were:
solutions:
app:showAsAction
as "collapseActionView"
+ in java code need also to call searchView.setIconifiedByDefault(false)
for the expansion to take priority over the iconification (that is - when the icon is pressed, expand and don't stay in icon mode)MenuItem.OnActionExpandListener
for your search menu-item object
and use a handler to post a runnable that will request focus to your search-view object
.
(why runnable? because requesting focus when the menu is still not fully inflated is not guaranteed to work. When requesting focus in a handler-runnable, I'm making sure the focus request happens AFTER all the work in the onCreateOptionsMenu()
is ready and finished.complete code solving all those problems:
menu.xml:
<item
android:id="@+id/searchContacts"
android:icon="@drawable/ic_search_white_24dp"
android:title="search"
app:showAsAction="collapseActionView|always"
app:actionViewClass="android.widget.SearchView"
/>
<!-- and of course your other menu items -->
searchable configuration:
Need to create such xml file.
right-click your res
folder and choose new --> android resource file
. put whatever you want as file name ("searchable" will work ok, for example), and choose XML
as resource type.
Then copy & paste this code in the created file (replace the hint string with your own):
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="put here your hint string to be shown"
/>
MainActivity:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
implementSearch(menu);
return true;
}
private void implementSearch(final Menu menu) {
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final MenuItem searchMenuItem = menu.findItem(R.id.searchContacts);
final SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
searchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener(){
@Override
public boolean onMenuItemActionExpand(MenuItem item){
// the search view is now open. add your logic if you want
new Handler().post(new Runnable() {
@Override
public void run() {
searchView.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) { // it's never null. I've added this line just to make the compiler happy
imm.showSoftInput(searchView.findFocus(), 0);
}
}
});
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item){
// the search view is closing. add your logic if you want
return true;
}
});
}
Also, if you want to use your own callbacks for the search's text change and submitted (instead of Android intents), in the implementSearch()
method add a call to searchMenuItem.setOnActionExpandListener(new SearchView.OnQueryTextListener({...}))
.
view this SO question for more details
Upvotes: 6