I'm having a bad time with my Searchview on Android dev.
I'm trying to implement the Searchview on my toolbar's app. For now it's working very well but when I rotate the device, the search view behaves strangely.
My objective is persist the query text, so on "OnCreateOptionsMenu"
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_funcionarios_toolbar, menu);
clearSearchItem = menu.findItem(R.id.botao_limpar_busca);
searchItem = menu.findItem(R.id.botao_buscar);
searchItem.setIcon(new IconicsDrawable(getContext(), MaterialDesignIconic.Icon.gmi_search).sizeDp(24));
searchView = (SearchView) searchItem.getActionView();
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setOnQueryTextListener(searchViewTextListener);
searchView.post(new Runnable() {
#Override
public void run() {
if (!mQuery.equals("")) {
searchView.setQuery(mQuery,false);
}
}
});
if (mQuery != null & !mQuery.equals("")) {
searchItem.expandActionView();
}
}
But If I use .expandActionView(), after the rotation (and cleaning the field using the "X" button provided by the SearchView), the MenuItem turns into those 3 little dots without any action. To restore the previous behaviour, I have to rotate the device again.
I'm almost sure the problem is on my XML:
<item
android:id="#+id/botao_buscar"
android:title="#string/menu_buscar"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
Changing the "showAsAction" attribute to "always" worked like a charm.
Any thoughts on this ?
Finally, I found a solution in this site: LINK. (Thank you so much for this post.)
I copy the code here because It's could be a dependency.
<item
android:id="#+id/menu_main_action_search"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/menu_main_search_title"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView" />
Code:
searchMenuItem.expandActionView();
mSearchView.setQuery(mSearchString, true);
mSearchView.clearFocus();
Finally the 3 dot not appear again. There is a search icon !! awesome
I had similar problem and solved it like this.
In onCreateOptionsMenu:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu, menu);
MenuItem item = menu.findItem(R.id.search_option);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(searchQueryListener);
if(searchQuery!=null && !searchQuery.equals("")) {
searchView.setIconified(false);
searchView.setQuery(searchQuery,true);
searchView.clearFocus();
}
}
For the searchView menu item:
<item
android:id="#+id/search_option"
android:title="#string/button_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
In my case I have another menu item with icon to the right of the search view and this way it works fine when rotating the device.
To overcome the ugly search bar resulting from showAsAction="always", I solved this way (keeping showAsAction="collapseActionView|ifRoom"):
public boolean onCreateOptionsMenu(Menu menu) {
...
if (!TextUtils.isEmpty(mQuery))
new Handler().post(() -> {
searchView.clearFocus();
searchView.setIconified(false);
searchItem.expandActionView();//or MenuItemCompat.expandActionView for older devices
searchView.setQuery(mQuery, false);//or true here if you want it submitted!
});
}
The trick is to call searchItem.expandActionView() after searchView.setIconfied(false).
For increased stability, I keep the whole sequence in a post - as you did - but it looks like is working better to have a new Handler() to do it.
Related
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.)
Application
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.
I've also encountered a similar problem, and was able to solve it.
The main problems I've needed to solve were:
searchView was not expanding by default
the search EditText didn't get a focus until a second click
even after solving (2), the keyboard didn't show up until a second click
solutions:
in menu.xml need to define 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)
add a 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.
in The same defined runnable from (2), also ask android OS to show the keyboard.
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
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"
/>
I am trying to animate between the visibility mode for a menu.
By default all menu items are hidden but when the user clicks on the edit button i want to show all the items with an animation.
I have achieved the first part of changing the visibility of the menu items and that works fine but the animation part crashes the app.
Here is my code.
When user clicks on edit this is called.By default edit_mode is false.
if (!edit_mode) {
edit_mode = true;
supportInvalidateOptionsMenu();
}
This is the menu code.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_add__custom, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem photo = menu.findItem(R.id.photo);
photo.setVisible(edit_mode);
if (edit_mode)
photo.getActionView().animate().alpha(1.0f);
MenuItem date = menu.findItem(R.id.date);
date.setVisible(edit_mode);
if (edit_mode)
date.getActionView().animate().alpha(1.0f);
MenuItem done = menu.findItem(R.id.done);
done.setVisible(edit_mode);
if (edit_mode)
done.getActionView().animate().alpha(1.0f);
return edit_mode;
}
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#+id/date"
android:icon="#drawable/ic_event_white_24dp"
android:orderInCategory="200"
android:title="Date"
app:showAsAction="ifRoom" />
<item
android:id="#+id/done"
android:icon="#drawable/ic_done_white_24dp"
android:orderInCategory="300"
android:title="Done"
app:showAsAction="ifRoom" />
<item
android:id="#+id/photo"
android:icon="#drawable/ic_photo_white_24dp"
android:orderInCategory="100"
android:title="Done"
app:showAsAction="ifRoom" />
I sure that crash that you are having is there because of NullException thrown by getActionView(). First of all to animate that way you have set the actionView first during onCreateOptionMenu(). That way when you get the actionView in onPrepareOptionsMenu it wont crash because of that and then you can animate it. The onPrepareOptionsMenu executes when you press the menu button so your logic to animate it that time is correct.
If its just the text you want to show in menu item, it should go like this,
final MenuItem photo;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_my_report, menu);
photo = menu.findItem(R.id.action1);
TextView textView = new TextView(this);
textView.setText("I am menu item");
photo.setActionView(textView);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(someCondition)
{
photo.getActionView().animate().alpha(1.0f);
}
return super.onCreateOptionsMenu(menu);
}
In case you want to have the a complex and customise text you can set it using the layoutInflator service. This could go in your onCreate,
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageView view = (ImageView)inflater.inflate(R.layout.some_view, null);
Animation rotation = AnimationUtils.loadAnimation(this, R.anim.fade);
and onCreateOptionMenu,
view.startAnimation(rotation);
photo.setActionView(view);
Its just to get you an idea what needed to be done, you can play around with this and can suit your need.
I'm having big problems opening and closing the keyboard using a searchview in my toolbar as actionbar. When I hit the searchbutton it expends as a action and the edit text appears, but it has no focus and they keyboards doesnt open. I have to manually click on the edittext to open the keyboard.
The same for closing the keyboard. When i hit the close searchaction button, they keyboard wont close.
I'm sure that this already worked without using the toolbar.... but I'm not able to fix it with toolbar.
Does anybody have an idea ?
This is my menu :
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.toolbar.MainActivity" >
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_action_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.widget.SearchView"
android:title="#string/action_search"/>
<item
android:id="#+id/action_contact"
android:icon="#drawable/ic_action_settings"
app:showAsAction="ifRoom"
android:title="#string/action_settings"/>
And this is my onCreateOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
// Do not iconify the widget;expand it by default
searchView.setIconifiedByDefault(false);
setSearchIcons();
return super.onCreateOptionsMenu(menu);
}
Thanks for any advice.
Cheers!
EDIT1:
Well obviously after 10 hours of struggle I ask this question and 30min later I find a solution.
It was the app:showAsAction="ifRoom|collapseActionView"
collapseActionView. Deleting it did the trick.
But now I have another problem. When the search view expands the settings button looks very bad. The settings button is half visible/ half cut out.
On API 21 Nexus 4 Android 5 the search view cuts out the settings button.
On a THL 5000 with Android 4.4.2 the search view seems to work fine, but the icons are not white as on the Nexus but grey.
Any idea?
If your searchView is not always in expanded state, then you can try below code:
mSearchView.setIconifiedByDefault(true);
mMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Add code here
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Add code here
return false;
}
});
To hide keyboard after clicking enter/done on keyboard:
#Override public boolean onQueryTextSubmit(String query) {
mSearchView.clearFocus();
return true;
}
I'm busy with changing my existing app to material design, but i'm having trouble with the menu items inside the ActionBar.
First of all in some activities i'm using a searchview, But i have read that you need to use a custom prefix inside the searchview menu xml. So i did:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_action_search_light"
android:title="Search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
But everytime I'm getting the error:
"Should use android:showAsAction when not using the appcompat library"
if i change app:showAsAction="ifRoom|collapseAction" to android:showAsAction="ifRoom|collapseActionView"
I'm not getting a searchview that take the whole lenght of the actionbar, just some strange square in the right corner where the items are placed. Here is my code of the onCreateOptionsMenu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.searchview, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView search = (SearchView) MenuItemCompat.getActionView(searchItem);
if(search != null)
{
search.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(search.getWindowToken(), 0);
try {
new LoadResultsTask().execute(URLEncoder.encode(query, "UTF-8"));
} catch (UnsupportedEncodingException e) {
Toast.makeText(IndexerOverviewActivity.this, "Could not parse Query", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
return true;
}
#Override
public boolean onQueryTextChange(String search) {
return true;
}
});
}
search.setIconifiedByDefault(false);
return super.onCreateOptionsMenu(menu);
}
I noticed aswell that all my actionbar menu items that has android:showsAsAction="always" are shown as android:showsAsAction="never" when i start my application on my device. So my first guess is it has everything to do with the prefix to use in the menu xml files.
Pffff, after just a single "clean" it works perfectly now...
It took me freaking 2 hours to fix this.
I have implemented an android SearchView in ActionBar. When the SearchView gains focus, the close button [x] at the right shows up. I took a look at other android native apps, like Contacts and Gmail. The close button is not shown when the SearchView gains focus.
How to set my SearchView behave like that?
Setting searchView.setIconifiedByDefault(false) will disable collapsing the search view and also remove the close button.
I faced the same problem with android.support.v7.widget.SearchView and found a solution. First, in onCreateOptionsMenu, you can obtain a reference to the SearchView as well as its close button:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
try {
Field searchField = SearchView.class.getDeclaredField("mCloseButton");
searchField.setAccessible(true);
mSearchCloseButton = (ImageView) searchField.get(mSearchView);
} catch (Exception e) {
Log.e(TAG, "Error finding close button", e);
}
}
Now you can try to modify the button. First I tried to use setVisibility(View.GONE) to hide the close button, but that doesn't work, because the SearchView resets the visibility of its close button when the user interacts with the SearchView. So my solution was to use a transparent drawable and disable the click of the close button:
if (mSearchCloseButton != null) {
mSearchCloseButton.setEnabled(false);
mSearchCloseButton.setImageDrawable(getResources().getDrawable(R.drawable.transparent));
}
This article helped me as well:
http://novoda.com/blog/styling-actionbar-searchview
However, this is quite hacky to be honest. It would be cleaner to grab the SearchView source from https://android.googlesource.com/platform/frameworks/support.git/+/master/v7/appcompat/src/android/support/v7/widget/SearchView.java and create your own version of SearchView that does the hide/show of the close button.
Update:
Google just announced AppCompat v21, which has styling improvements for the SearchView widget:
http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html
You can also use this to hide the close the button
ImageView closeBtn = (ImageView) searchView.findViewById(R.id.search_close_btn);
closeBtn.setEnabled(false);
closeBtn.setImageDrawable(null);
Posting for future visitors. Previous answers are old and not easy. All you have to do is to set null to app:closeIcon this way app:closeIcon="#null"
<androidx.appcompat.widget.SearchView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:closeIcon="#null" <!-- This simple solution -->
app:iconifiedByDefault="false" />
You can get a link to the button from a SearchView object (AppCompat v23.2.1):
searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
ImageView mCloseButton = (ImageView) searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);
Then you can assign a listener to the SearchView text changes (SearchView also changes the visibility of the button, but the listener will be executed afterwards and will override those changes):
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
mCloseButton.setVisibility(newText.isEmpty() ? View.GONE : View.VISIBLE);
return false;
}
});
And finally, a listener to hide the icon when SearchView is expanded from iconified state:
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// hide "x" button if there is no text
String query = searchView.getQuery().toString();
mCloseButton.setVisibility(query.isEmpty() ? View.GONE : View.VISIBLE);
}
});
With AndroidX, android.support.v7.appcompat.R.id.search_close_btn won't work
This will do the trick,
app:closeIcon="#null"