Auto Collapse ActionBar SearchView on Soft Keyboard close

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.