I did a search widget, which works fine. But when I pressed the back button, onCancel and onDismiss are never call.
In the PCRListActivity.java :
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) this.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
// Assumes current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
searchManager.setOnCancelListener(new SearchManager.OnCancelListener() {
#Override
public void onCancel() {
getLoaderManager().restartLoader(LOADER_ID_PRODUCTS, null, PCRListActivity.this);
}
});
searchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
#Override
public void onDismiss() {
getLoaderManager().restartLoader(LOADER_ID_PRODUCTS, null, PCRListActivity.this);
}
});
return true;
}
So, what am I doing wrong ?
I also meet this problem, and I have no choice but give up "oncloselistener". Instead, you can get your menuItem, then setOnActionExpandListener. Then override unimplents methods.
I guess that close and dissmiss methods just work for Progress Dialogs.
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
//do what you want to when close the sesarchview
//remember to return true;
return true;
}
Related
I have SearchView which I want to programmatically expand and set text when the device orientation change. I tried many found solution but nothing work. If I use only setQuery then my list is filtered, but when I use also expandActionView then the search view does not contain the given search text and onQueryTextChange is called twice, first with the given text and the second time with the empty text.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.activity, menu);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
searchView.setIconifiedByDefault(true);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
searchView.setOnQueryTextListener(this);
MenuItemCompat.setOnActionExpandListener(searchMenuItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
mCurrentQueryString = null;
if (mAdapter != null) {
mAdapter.clearFilter();
mStopSearching = true;
}
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
if (mAdapter != null) {
mStopSearching = false;
}
return true;
}
});
mSearchView = searchView;
mSearchMenuItem = searchMenuItem;
mSearchView.post(new Runnable() {
#Override
public void run() {
MenuItemCompat.expandActionView(mSearchMenuItem);
mSearchView.setQuery(mCurrentQueryString, true);
}
});
super.onCreateOptionsMenu(menu, inflater);
}
I use the search view in the fragment which is used in the view pager. The fragment is retained. The problem is that onQueryTextChange function is called twice, by the second time with the empty text, but I am not sure why. This function is also called with the empty text when I first time open the search view when the fragment is initialized, but when close the serach view and open it again, this function is not called.
How can I fix it?
I've also faced that issue. The solution I've come up with was via posting with handler.
#Override public boolean onPrepareOptionsMenu(Menu menu) {
...
// SearchView doesn't retain it's state after orientation change
// have to handle it the bad way (╯°□°)╯︵ ┻━┻
boolean isQueryExists = !TextUtils.isEmpty(mSearchQuery);
if (isQueryExists) {
// Calling directly doesn't take effect
// Custom runnable class in order to refrain from context leakage
new Handler(Looper.getMainLooper()).post(new SearchMenuRunnable(mSearchView, mSearchQuery));
}
...
}
SearchMenuRunnable.java
public class SearchMenuRunnable implements Runnable {
private WeakReference<SearchView> mSearchViewWeakReference;
private String mSearchQuery;
public SearchMenuRunnable(SearchView searchView, String searchQuery) {
mSearchViewWeakReference = new WeakReference<>(searchView);
mSearchQuery = searchQuery;
}
#Override public void run() {
if (null != mSearchViewWeakReference.get()) {
SearchView searchView = mSearchViewWeakReference.get();
searchView.setIconified(false);
searchView.setQuery(mSearchQuery, true);
searchView.clearFocus();
}
}
This are source from one of projects in github. You can examine them here, it's pretty simple project.
I have an action bar that is attached to my main activity. There are many different fragments that the activity hosts. In the action bar there are menu items. One is a search view. I have this declared as follows:
menu xml.
<item android:id="#+id/action_search"
android:title="#string/search"
android:icon="#drawable/ic_search_black"
app:showAsAction="always"
app:actionViewClass= "android.support.v7.widget.SearchView"/>
In Main Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
// Associate searchable configuration with the SearchView
MenuItem item = menu.findItem(R.id.action_search);
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
The search view works, when I click the icon the search view expands. I need to capture the click of the search view, as when the user clicks the search view I want to display a view showing the user a list of their recent searches.
I will also be using the search view like so:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search)
.getActionView();
if (null != searchView) {
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
}
SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
public boolean onQueryTextChange(String newText) {
// this is your adapter that will be filtered
return true;
}
public boolean onQueryTextSubmit(String query) {
//Here u can get the value "query" which is entered in the search box.
}
};
searchView.setOnQueryTextListener(queryTextListener);
return super.onCreateOptionsMenu(menu);
}
and carry out the search when the user types 3 characters or more.
I have tried this in the activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()){
case R.id.action_search:
L.i("search", "search");
return false;
case android.R.id.home:
L.i("home", "home pressed");
break;
case R.id.action_done:
L.i("done", "done pressed");
break;
default:
;;
}
return super.onOptionsItemSelected(item);
}
It recognises the done menu item but not the search. I will need to be able to pick up the click in activity and fragment.
So if anyone can point out where I'm going wrong.
Oh, in fragment I've added
setHasOptionsMenu(true);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()){
case R.id.action_search:
L.i("search", "search");
return false;
case android.R.id.home:
L.i("home", "home pressed");
break;
case R.id.action_done:
//for testing
checkSelectedInterests();
//TODO: MLC
L.i("done", "done pressed");
break;
default:
;;
}
return super.onOptionsItemSelected(item);
}
so if anyone can help I'd appreciate it
So I figured this out. From what I can gather this can't be done via the onOptionsItemSelected method.
So I then set an onclicklistener on the search view which didn't work either. On closer inspection I needed to set and onSearchClickListener as follows:
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
L.i(getClass().getSimpleName(), "SearchViewCLicked");
}
});
Hopefully that'll help someone out!
Here is the simple solution to this, set an onActionExpandListener to the menu item as shown below:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu, menu);
// Get the MenuItem for the action item
MenuItem actionMenuItem = menu.findItem(R.id.action_search);
// Define the listener
actionMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do what you want when it expands
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do what you want when it collapses
return true;
}
});
return true;
}
I am not able to get the filter value from the list.
For the wrong search the list shows blank page, when I enter the right value, only the first value from the list is fetched.
After implementing OnQueryTextListener to my class, I inserted the following code:-
Please help. Thanks in Advance
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
SearchManager searchManager = (SearchManager) getSystemService( Context.SEARCH_SERVICE );
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(this);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if(TextUtils.isEmpty(newText)){
lv.clearTextFilter();
}else{
lv.setFilterText(newText.toString());
}
// TODO Auto-generated method stub
return true;
}
Implementing Filterable in Adapter class
public Filter getFilter(){
return null;
}
I Added the above method, now there is NullPointerException generated.
Check out this tutorial it uses Sherlock Action Bar, it shows exactly what you are trying to do. I have used it and works great. http://www.androidbegin.com/tutorial/implementing-actionbarsherlock-search-collapsible-view-in-android/
I am using SearchView and it is working fine but only setOnCloseListener is not working; Here is my code
import com.actionbarsherlock.widget.SearchView.OnCloseListener;
and
searchView.setOnCloseListener(new OnCloseListener() {
#Override
public boolean onClose() {
Toast.makeText(context, "close", Toast.LENGTH_SHORT).show();
return false;
}
});
**EDIT****
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//Used to put dark icons on light action bar
//Create the search view
final SearchView searchView = new SearchView(getSupportActionBar().getThemedContext());
searchView.setQueryHint("Search");
searchView.setIconifiedByDefault(true);
//search button
menu.add(Menu.NONE,Menu.NONE,1,"Search a word")
.setIcon(R.drawable.abs__ic_search_api_holo_light)
.setActionView(searchView)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
MenuItem sView = menu.findItem(1);
sView.setOnActionExpandListener(this);
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
adopter.getFilter().filter(null);
Toast.makeText(getApplicationContext(), "collapse", Toast.LENGTH_LONG).show();
return true; // Return true to collapse action view
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
Toast.makeText(getApplicationContext(), "Expand", Toast.LENGTH_LONG).show();
return true; // Return true to expand action view
}
Solved it by myself. Just leave setOnCloseListener it will not work, and put following code in onCreateOptionsMenu
// searchView.setOnCloseListener(new OnCloseListener() {
// #Override
// public boolean onClose() {
// adapter.getFilter().filter("");
// Toast.makeText(getBaseContext(), "on close", Toast.LENGTH_SHORT).show();
// return false;
// }
// });
MenuItem menuItem = menu.findItem(ID_OF_SEARCHVIEW);
menuItem.setOnActionExpandListener(new OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
adapter.getFilter().filter("");
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
adapter.getFilter().filter("");
return true;
}
});
I have encountered the same problem with onCloseListener not invoking for the SearchView.
Understand from the bug issue raised in 25758, and some postings I have read, to invoke onCloseListener, you need to set:
searchView.setIconifiedByDefault(true);
But for my case I wanted to have the search view opened & not iconified all the time. I manage to resolve this by adding one more line below:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_bar, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(queryTextListener);
searchView.setIconifiedByDefault(true);
searchView.setIconified(false);
return true;
}
The searchView.setIconified(false) will cause the searchView to open up, despite setting the default to iconified to true in the previous line. In this way, I managed to have both a SearchView
that opens up all the time & having it invoke the onCloseListener.
I'm using this code. And it works perfectly
#Override
public void onStartSearch() {
}
#Override
public void onSearch(String search) {
}
#Override
public void onCloseSearch() {
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.your_menu, menu);
// Associate searchable configuration with the SearchView
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem); //here I user appcompat, but you can take it just from actionbarsherlock
SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchAutoComplete.setTextColor(getResources().getColor(R.color.action_bar_text_color));
mSearchView.setIconifiedByDefault(true);
mSearchView.setSubmitButtonEnabled(false);
/**
* Set all of different kinds of listeners
*/
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
menuIsOpen = false;
onCloseSearch();
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
menuIsOpen = true;
onStartSearch();
return true;
}
});
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String s) {
onSearch(s);
return false;
}
#Override
public boolean onQueryTextSubmit(String s) {
onSearch(s);
return true;
}
});
super.onCreateOptionsMenu(menu, inflater);
}
/**
* Function for closing search when android is less than 14
*/
public boolean onBackButton() {
if (AndroidUtils.getSdkVersion() >= 14)
return false;
if (menuIsOpen) {
menuIsOpen = false;
getActivity().supportInvalidateOptionsMenu();
onCloseSearch();
return true;
}
return false;
}
After backButton it close search, or just by selecting close from action bar.
You can use a OnActionExpandListener:
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
SearchView searchView = new SearchView(((SherlockFragmentActivity) getActivity()).getSupportActionBar().getThemedContext());
searchView.setIconifiedByDefault(true);
// ...
MenuItem menuItem = menu.add(R.string.search);
// ...
menuItem.setOnActionExpandListener(this);
}
#Override
public boolean onMenuItemActionExpand(final MenuItem item) {
mInSearchMode = true;
return true;
}
#Override
public boolean onMenuItemActionCollapse(final MenuItem item) {
mInSearchMode = false;
return true;
}
I am currently using an ActionBar menu item to display a SearchView in the action bar. When the search menu item is expanded the soft keyboard is displayed which is what I want. Now, when the user presses the back button to close the soft keyboard, I would also like to collapse the SearchView in the action bar.
I have tried implementing the following listeners OnKeyListener and OnFocusChangeListener on the MenuItem and the ActionView. I have also tried using OnBackPressed() in the Activity. None of the above detect when the back button is used to close the soft keyboard.
Any ideas?
I have implemented OnActionExpandListener to know when the SearchView is visible.
I'll expand on #user1258568 's answer for the lazy. This worked for me. Note that it clears your query when focus is lost.
final MenuItem searchMenuItem = optionsMenu.findItem(R.id.search);
final SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean queryTextFocused) {
if(!queryTextFocused) {
searchMenuItem.collapseActionView();
searchView.setQuery("", false);
}
}
});
I found a better solution.
searchView.setOnQueryTextFocusChangeListener().
The OnQueryTextFocusChangeListener gets called when the keyboard is displayed or hidden. Gets called first when the keyboard is displayed and the search view will have focus. Gets called again when keyboard is hidden and search view will lose focus, can close search viewthen using
menuItem.collapseActionView().
Just Override onBackPressed like this:
#Override
public void onBackPressed() {
if (searchView.isShown()){
searchView.onActionViewCollapsed(); //collapse your ActionView
searchView.setQuery("",false); //clears your query without submit
isClosed = true; //needed to handle closed by back
} else{
super.onBackPressed();
}
}
and your onCreateOptionsMenu would inflate the mSearchView like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_search, menu);
mSearchView = (SearchView) menu.findItem(R.id.menu_action_search).getActionView();
mSearchView.setOnQueryTextListener(this);
mSearchView.setOnSearchClickListener(this);
mSearchView.setOnCloseListener(this);
isClosed = true;
return true;
}
have you class implement the following like this:
public class myActivity extends FragmentActivity implements
SearchView.OnQueryTextListener, View.OnClickListener, SearchView.OnCloseListener {
which you will also need:
#Override
public void onClick(View view) {
isClosed = false;
}
#Override
public boolean onClose() {
isClosed = true;
return false;
}
You will need to make "mSearchView" and "isClosed" both global variables to the activity.
The answer from Jon Willis works great. This is an improvement to his answer.
First, create a new class that implements View.OnFocusChangeListener:
public class SearchViewFocusListener implements View.OnFocusChangeListener {
private final MenuItem mMenuItem;
public SearchViewFocusListener(MenuItem menuItem) {
mMenuItem = menuItem;
}
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
mMenuItem.collapseActionView();
if (v instanceof SearchView) {
((SearchView) v).setQuery("", false);
}
}
}
}
Next, set the listener on your SearchView:
searchView.setOnQueryTextFocusChangeListener(new SearchViewFocusListener(menuItem));
You only need to put the "collapseActionView" attribute in the menu layout
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_item_search"
android:title="#string/search"
android:iconifiedByDefault="true"
android:icon="#drawable/ic_action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView"/> <--this one
</menu>
That will give you the functionality you look for all by itself.Don't forget to call the method "clearFocus" on the SearchView to close the keyboard once you send the query.
This is what I did for making the keyboard disappear. You can try to see if this works for you. I set the searchView to invisible and then to visible again.
//set query change listener
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextSubmit(String query) {
/**
* hides and then unhides search tab to make sure keyboard disappears when query is submitted
*/
searchView.setVisibility(View.INVISIBLE);
searchView.setVisibility(View.VISIBLE);
return false;
}
});
It's achievable like this:
private void setupSearchView(Menu menu) {
final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) searchMenuItem.getActionView();
[...]
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
searchMenuItem.collapseActionView();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
}
Solutions based on setOnQueryTextFocusChangeListener() did not work for me because the event was not launched - the searchView did not lose focus when submitted, probably because I perform the search in the same activity that contains the Search View.
Anyway, I think using OnQueryTextListener is more correct, as it describes the event of submitting text more precisely.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.home_screen, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
final SearchView searchView = (SearchView) searchMenuItem
.getActionView();
searchView.setIconifiedByDefault(false);
if (searchManager != null && searchView != null) {
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView
.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
if (searchMenuItem != null) {
searchMenuItem.collapseActionView();
}// end if
if (searchView != null) {
searchView.setQuery("", false);
}// end if
}// end if
}
});
searchView
.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
/**
* hides and then unhides search tab to make sure
* keyboard disappears when query is submitted
*/
if (searchView != null) {
searchView.setVisibility(View.INVISIBLE);
searchView.setVisibility(View.VISIBLE);
}
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
});
}
return super.onCreateOptionsMenu(menu);
}
If you want to collapse keyboard when user clicks search icon on keyboard
this can be achieved by simple
inside onquerytextsubmitted {
searchView.clearfocus()
}
You need to call setIconified twice.
To actually collapse your search view and close the keyboard.
With first call text of search view is cleared with second call keyboard and search view get closed.
For some reason, menuItem.collapseActionView() did not work so I used searchView.setIconified(true) instead.
This gives the below result as the code sample.
final MenuItem searchItem = (MenuItem) menu.findItem(R.id.menu_item_search);
final SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextFocusChangeListener(new SearchView.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
searchView.setIconified(true);
}
}
});