24

I'm using a single activity to display SearchView as well as to display search results. The search results is just a subset of items so the search acts as a filter. Everything seems to work fine except that I can't figure out how to restore all items in the view when a back button of SearchView is clicked on.

Or maybe there is another way to detect when a user navigates from search results to the previous view (which, in my case, is the same view).

Thanks

bdristan
  • 1,048
  • 1
  • 12
  • 36
  • Take a look here http://stackoverflow.com/questions/25842555/how-to-handle-back-button-of-search-view-in-android – Matei Radu May 04 '16 at 23:19
  • 1
    Matei Radu, Thanks for the link which provides all the info I needed - including expanding on th3pat3I answer. – bdristan May 05 '16 at 14:23
  • 1
    @bdristan after I updated my answer I see now that @MateiRadu supplied you with the correct answer for listening to opening/closing the `SearchView`. However I hope my answer still helps as it has somewhat the explanation to why it doesn't work anymore :-) – Darwind May 05 '16 at 16:38
  • @Darwind you should add the link I shared at the bottom of your answer to make it an even more complete solution for future viewers if bdristan wants to mark it as accepted. – Matei Radu May 05 '16 at 20:00
  • 1
    @MateiRadu I just did - at least for completeness it helps - it's so irritating to read an answer and you kinda feel you're missing something in the understanding ;-) – Darwind May 05 '16 at 23:54

5 Answers5

48

So looking at the title of your question, you're not sure how to detect when the SearchView is being closed and hence you're not able to restore your views to the "normal" state when the SearchView is not open anymore.

Outdated solution as of Android 4.0+

The (simple) solution is to add a: SearchView.OnCloseListener to your SearchView, like this:

SearchView.setOnCloseListener(new SearchView.OnCloseListener() {
    @Override
    public boolean onClose() {
        // This is where you can be notified when the `SearchView` is closed
        // and change your views you see fit.
    }
});

EDIT:

Updated solution that works in Android 4.0+

Apparently the OnCloseListener is buggy and doesn't work on newer versions of Android (4.0+). See: https://code.google.com/p/android/issues/detail?id=25758

The solution to this is to use the Support library version of the SearchView:

My onCreateOptionsMenu looks like this:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);

    MenuItem searchMenuItem = menu.findItem(R.id.searchView);
    SearchView searchView = (SearchView) searchMenuItem.getActionView();

    MenuItemCompat.setOnActionExpandListener(searchMenuItem, new MenuItemCompat.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            Toast.makeText(ScrollingActivity.this, "onMenuItemActionExpand called", Toast.LENGTH_SHORT).show();
            return true;
        }

        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            Toast.makeText(ScrollingActivity.this, "onMenutItemActionCollapse called", Toast.LENGTH_SHORT).show();
            return true;
        }
    });
}

As to why Google didn't even bothered to write a comment in the documentation I don't know, but it's sad.

EDIT2:

Just adding the link which @MateiRadu added in the comments:

how to handle back button of Search View in android

This also shows how to use the OnActionExpandListener instead of the OnCloseListener.

Hope this helps.

Community
  • 1
  • 1
Darwind
  • 7,284
  • 3
  • 49
  • 48
  • Unfortunately onClose() is not being called when SearchView closes. However, onQueryTextSubmit() and onQueryTextChange() - as suggested by th3pat3l - do get called. Ideally I'd like to utilize all three listeners. – bdristan May 05 '16 at 13:39
  • If you have your own SearchView custom class use: @Override public void onActionViewCollapsed() { super.onActionViewCollapsed(); } – Mike6679 Oct 02 '17 at 18:31
  • MenuItemCompat is now deprecated. Try MenuItem.setOnActionExpandListener(); https://developer.android.com/reference/android/view/MenuItem.OnActionExpandListener.html – anoo_radha Feb 05 '18 at 16:06
  • **MenuItemCompat.setOnActionExpandListener() is deprecated. Solution:** https://stackoverflow.com/questions/48989235/menuitemcompat-setonactionexpandlistener-deprecated – Johnny Five Feb 19 '19 at 11:41
11

All code here is deprecated ! You should use something like this.

final MenuItem item = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) item.getActionView();

item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {

            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                Toast.makeText(getActivity(), "onMenuItemActionExpand called", Toast.LENGTH_SHORT).show();
                return true;
            }

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                Toast.makeText(getActivity(), "onMenutItemActionCollapse called", Toast.LENGTH_SHORT).show();
                return true;
            }
        });

Hope that will help.

Zhar
  • 3,330
  • 2
  • 24
  • 25
4

Darwind's answer will do the job but that only works when user presses the back button to close the keyboard and when SearchView doesn't have focus anymore.

The better way to do it is to listen for SearchView's text changes.
This way you can restore views and control UI as the text is updating.
here's how I do it.

SearchView searchView = new SearchView(context);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        // this is when user is done typing and clicks search
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        // you can use this to do a "live" search while the user is typing.
        // this will trigger each time user changes (adds or removes) text
        // so when newText is empty, restore your views
        return false;
    }
});
ᴛʜᴇᴘᴀᴛᴇʟ
  • 4,466
  • 5
  • 39
  • 73
4
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    searchView = (SearchView) MenuItemCompat.getActionView(searchItem);

  
    searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean newViewFocus) {
            if (!newViewFocus) {
                //Collapse the action item.
                searchItem.collapseActionView();
                //Clear the filter/search query.
                myFilterFunction("");
            }
        }
    });

    return super.onCreateOptionsMenu(menu);
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
-1

There is one other trick:

searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
                @Override
                public void onSearchViewShown() {
                    if(!txtToolbarTitle.getText().toString().isEmpty()){
                        searchView.setQuery(txtToolbarTitle.getText().toString()+ " ", false);
                    }
                }

                @Override
                public void onSearchViewClosed() {
                    if(txtToolbarTitle.getText().toString().isEmpty()){
                        finish();
                    }
                }
            });
Sagar Chavada
  • 5,169
  • 7
  • 40
  • 67