如何以编程方式关闭SearchView?


71

我目前SearchView在应用程序的操作栏中有一个。当我单击搜索图标时,将SearchView展开并按预期弹出键盘。单击SearchView框中的“ X”关闭SearchView按预期的方式。但是,当SearchView激活并按下“后退”按钮时,我的应用程序退出。这是正确的行为,但是我现在要做的是捕获后退按钮的按下,并SearchViewSearchView可见时关闭它(而不是我的应用程序)。有没有办法SearchView OnCloseListener()在按下后退按钮时以编程方式调用?例如,如下所示:

// On a back button press, if we are currently searching,
// close the SearchView. Otherwise, invoke normal back button
// behavior.
public boolean onKeyDown(int keyCode, KeyEvent event) {
   if (keyCode == KeyEvent.KEYCODE_BACK) {
        if (isSearchViewVisible) {
            SearchView searchView = (SearchView) menu.findItem(R.id.searchBox)
               .getActionView();

            // This method does not exist
            searchView.invokeClose();
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

Answers:


158

基于@MarcinOrlowski答案,您还可以使用:

@Override
public void onBackPressed() {
    if (!searchView.isIconified()) {
        searchView.setIconified(true);
    } else {
        super.onBackPressed();
    }
}

9
Important, the above solution won't work if the you have set app:showAsAction="always"
UserK

12
Make sure to set searchView.setQuery("", false); in order to make searchView.setIconified(true); to work
Pushan


40

There is a simple way to do this:

@Override
public void onBackPressed() {
    if (!searchView.isIconified()) {
        searchView.onActionViewCollapsed();
    } else {
        super.onBackPressed();
    }
}

or use:

myToolBar.collapseActionView();

This will make the searchView to collapse before you press the back then the back action will be called.

Both solutions will work.


1
collapseActionView not works, the first solution yes
Frank

32

this is the only thing that does it for me:

  toolbar.collapseActionView();

3
I tried all solution in this thread. this solution is the best for me. it is the only solution that made search icon back to top-right screen
Dika

IDE gives me "Actionbar.collapseActionView can only be called from within the same library group" error
Simon

1
supportActionBar?.collapseActionView() worked for me
HendraWD

23

To intercept BACK button override onBackPressed() (see docs)

@Override
public void onBackPressed() {

    if (isSearchViewVisible) {
        SearchView searchView = (SearchView) menu.findItem(R.id.searchBox)
           .getActionView();

        // This method does not exist
        searchView.invokeClose();
    } else {
        super.onBackPressed();
    }
}

EDIT:

Docs say:

If necessary, you can expand or collapse the action view in your own code by calling expandActionView() and collapseActionView() on the MenuItem.


Thanks for the response! What I'm mainly interested in though is whether there is a way to programmatically invoke a SearchView's close event i.e. Imitate an SearchView box "X" button press in code.
Tim

2
Thanks for all the help Marcin. It turns out what I actually wanted to do was the "iconify" my search actionview (my searchview is always on the action bar and never collapses into the options menu). Thanks for taking the time to help me and thanks for the tip on overriding "onBackPressed."
Tim

For me onBackPressed is not called. what other solution do I have ? I tried to listen for the focus on the searchview but that isn't called also..
Ionut Negru

You do not expect onBackPressed() outside of Activity (i.e. in Fragment), do you?
Marcin Orlowski

1
For me, onBackPressed not being called at all. It seems the search view is actually eating up the back press and handling it. For example, I see that onMenuItemActionViewCollapsed() is called, but onBackPressed is not called. How can I override this? I even tried setting a Key Listener on the search view and it still doesn't work.
Ashok SoThree

17

if you have input on your searchView

mSearchView.setIconified(true);

will only clear the text.

The correct method to close a searchView is

mSearchView.onActionViewCollapsed();


2

I prefer !searchView.isIconified() over if(isSearchViewVisible) inside the onBackPressed() method as option 2 does not work when you have fragments added in your fragmentmanager's backstack that you would like to show when the back button is pressed.


2

No need to use onBackPressed() method for this!! I found the solution, do only as I mentioned below so that the SearchView itself handle the on back button press event.

Inside your onCreateOptionsMenu() method,

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    MenuItem menuItem = menu.findItem(R.id.action_search);
    SearchView searchview = (SearchView) menuItem.getActionView();
    searchview.setIconifiedByDefault(true);
    searchview.setQueryHint("Enter your keyword");
    searchview.setOnQueryTextListener(this); 
    super.onCreateOptionsMenu(menu, inflater);
}

In your menu.xml add showAsAction attribute and set its values as "always|collapseActionView"

<item
    android:id="@+id/action_search_item"
    android:title="Search"
    android:icon="@drawable/ic_search_logo"
    app:showAsAction="always|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView"/>

And you're ready to go ;)

P.S. - I was searching for a solution from a long time and now I found one, hope it helps you all.


0

My way:

  1. Create CustomSearchView class
    public class CustomSearchView extends SearchView{
        public CustomSearchView(final Context context) {
            super(context);
            this.setIconifiedByDefault(true);
        }

        @Override
        public boolean dispatchKeyEventPreIme(KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && 
                event.getAction() == KeyEvent.ACTION_UP) {
                this.onActionViewCollapsed();
            }
            return super.dispatchKeyEventPreIme(event);
        }
    }

  1. Add actionViewClass
    <item
        android:id="@+id/menu_search"
        android:title="@string/menu_search"
        android:icon="@drawable/ic_search"
        android:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="com.myapp.CustomSearchView"/>
  1. Create CustomSearchView into onCreateOptionsMenu
    CustomSearchView searchView = (CustomSearchView)menu.findItem(R.id.menu_search).getActionView();

0

If you are not use any function in onBackPressed() method ,remove it from your Activity.So that the SearchView itself handle the onBackPress event.

I am using SearchView as

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchview = (SearchView) MenuItemCompat.getActionView(searchItem);
    searchview.setIconifiedByDefault(true);
    searchview.setOnQueryTextListener(this);
    searchview.setSubmitButtonEnabled(true);  
    searchview.setQueryHint("Search Here"); 
    super.onCreateOptionsMenu(menu, inflater);
}

and my menu.xml as follows

<item
    android:id="@+id/action_search"
    android:icon="@drawable/search_tool"
    android:orderInCategory="1"
    android:title="Search" 
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always|collapseActionView"/>

0

Also you can use collapseActionView. It automatically handle back button, collapsing SearchView

<item
      android:id="@+id/action_search"
      android:icon="@drawable/ic_magnify"
      android:title="@string/action_title_search"
      app:actionViewClass="android.support.v7.widget.SearchView"
      app:showAsAction="ifRoom|collapseActionView" />

0

The following worked for me. I am trying to close search-view from Fragment in Jetpack NavigationView when a user clicks the back button -

requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() {

        try {
            DashboardActivity activity = (DashboardActivity) getActivity();
            if (activity!=null) {
                if (!activity.mSearchView.isIconified()) {
                    activity.mSearchView.setQuery("",false);
                    activity.mSearchView.setIconified(true);
                } else {
                    NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment);
                    navController.popBackStack();
                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.