How to use SearchView in Toolbar Android

216,333

Solution 1

You have to use Appcompat library for that. Which is used like below:

dashboard.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        android:title="Search"/>
</menu>

Activity file (in Java):

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.dashboard, menu);

     MenuItem searchItem = menu.findItem(R.id.action_search);

    SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);

    SearchView searchView = null;
    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
    }
        return super.onCreateOptionsMenu(menu);
}

Activity file (in Kotlin):

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_search, menu)

    val searchItem: MenuItem? = menu?.findItem(R.id.action_search)
    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView: SearchView? = searchItem?.actionView as SearchView

    searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))
    return super.onCreateOptionsMenu(menu)
}

manifest file:

<meta-data 
      android:name="android.app.default_searchable" 
      android:value="com.apkgetter.SearchResultsActivity" /> 

        <activity
            android:name="com.apkgetter.SearchResultsActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>

searchable xml file:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name" />

And at last, your SearchResultsActivity class code. for showing result of your search.

Solution 2

If you would like to setup the search facility inside your Fragment, just add these few lines:

Step 1 - Add the search field to you toolbar:

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

Step 2 - Add the logic to your onCreateOptionsMenu()

import android.support.v7.widget.SearchView; // not the default !

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

    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    searchView = (SearchView) myActionMenuItem.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            // Toast like print
            UserFeedback.show( "SearchOnQueryTextSubmit: " + query);
            if( ! searchView.isIconified()) {
                searchView.setIconified(true);
            }
            myActionMenuItem.collapseActionView();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String s) {
            // UserFeedback.show( "SearchOnQueryTextChanged: " + s);
            return false;
        }
    });
    return true;
}

Solution 3

If you want to add it directly in the toolbar.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <SearchView
            android:id="@+id/searchView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:iconifiedByDefault="false"
            android:queryHint="Search"
            android:layout_centerHorizontal="true" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

Solution 4

Integrating SearchView with RecyclerView

1) Add SearchView Item in Menu

SearchView can be added as actionView in menu using

app:useActionClass = "android.support.v7.widget.SearchView" .

<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="rohksin.com.searchviewdemo.MainActivity">
<item
    android:id="@+id/searchBar"
    app:showAsAction="always"
    app:actionViewClass="android.support.v7.widget.SearchView"
    />
</menu>

2) Implement SearchView.OnQueryTextListener in your Activity

SearchView.OnQueryTextListener has two abstract methods. So your activity skeleton would now look like this after implementing SearchView text listener.

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3) Set up SerchView Hint text, listener etc

@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);

    MenuItem searchItem = menu.findItem(R.id.searchBar);

    SearchView searchView = (SearchView) searchItem.getActionView();
    searchView.setQueryHint("Search People");
    searchView.setOnQueryTextListener(this);
    searchView.setIconified(false);

    return true;
}

4) Implement SearchView.OnQueryTextListener

This is how you can implement abstract methods of the listener.

@Override
public boolean onQueryTextSubmit(String query) {

    // This method can be used when a query is submitted eg. creating search history using SQLite DB

    Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onQueryTextChange(String newText) {

    adapter.filter(newText);
    return true;
}

5) Write a filter method in your RecyclerView Adapter.

You can come up with your own logic based on your requirement. Here is the sample code snippet to show the list of Name which contains the text typed in the SearchView.

public void filter(String queryText)
{
    list.clear();

    if(queryText.isEmpty())
    {
        list.addAll(copyList);
    }
    else
    {

        for(String name: copyList)
        {
            if(name.toLowerCase().contains(queryText.toLowerCase()))
            {
                list.add(name);
            }
        }

    }

    notifyDataSetChanged();
}

Full working code sample can be found > HERE
You can also check out the code on SearchView with an SQLite database in this Music App

Solution 5

Implementing the SearchView without the use of the menu.xml file and open through button

In your Activity we need to use the method of the onCreateOptionsMenumethod in which we will programmatically inflate the SearchView

private MenuItem searchMenu;
private String mSearchString="";

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        SearchManager searchManager = (SearchManager) StoreActivity.this.getSystemService(Context.SEARCH_SERVICE);


        SearchView mSearchView = new SearchView(getSupportActionBar().getThemedContext());
        mSearchView.setQueryHint(getString(R.string.prompt_search)); /// YOUR HINT MESSAGE
        mSearchView.setMaxWidth(Integer.MAX_VALUE);

        searchMenu = menu.add("searchMenu").setVisible(false).setActionView(mSearchView);
        searchMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);


        assert searchManager != null;
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            public boolean onQueryTextChange(String newText) {
                mSearchString = newText;

                return true;
            }

            public boolean onQueryTextSubmit(String query) {
                mSearchString = query;

                searchMenu.collapseActionView();


                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);


        return true;
    }

And in your Activity class, you can open the SearchView on any button click on toolbar like below

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });
Share:
216,333
Shudy
Author by

Shudy

Enthusiastic Android developer.

Updated on November 14, 2021

Comments

  • Shudy
    Shudy over 2 years

    The code on which I am working, is using a Toolbar and inflating a menu.

    Here is the code

    private Toolbar mToolbar;
    mToolbar.inflateMenu(R.menu.chat_screen_menu);
    setupMenu ();
    private void setupMenu ()
       {
       mMenu = mToolbar.getMenu();
       if (mMenu != null)
          {
           if (mChatPager != null && mChatPager.getCurrentItem() > 0)
              {
              mMenu.setGroupVisible(R.id.menu_group_chats, true);
              mMenu.setGroupVisible(R.id.menu_group_contacts, false);
              }
           else
              {
               mMenu.setGroupVisible(R.id.menu_group_chats, false);
               mMenu.setGroupVisible(R.id.menu_group_contacts, true);
               mMenu.setGroupVisible(R.id.menu_group_otr_verified,false);
               mMenu.setGroupVisible(R.id.menu_group_otr_unverified,false);
               mMenu.setGroupVisible(R.id.menu_group_otr_off,false);
              }
        }
        mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener ()
        {
        ..........
        }
    }
    

    But now, they require a Search button in the tool_bar. I managed to put it, I followed a guide here When I try to write something to search, the toast I had put to test the listener never shown. which indicates listener is not working

    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
    
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.chat_screen_menu, menu);
    
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_menu_search));
        final Toast toast = new Toast(mApp);
    
        if (mSearchView != null )
        {
            mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
            mSearchView.setIconifiedByDefault(false);
    
            SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener()
            {
                public boolean onQueryTextChange(String newText)
                {
                    mSearchString = newText;
                    //doFilterAsync(mSearchString);
                    toast.makeText(getApplicationContext(), "Test1", Toast.LENGTH_LONG).show();
                    return true;
                }
    
                public boolean onQueryTextSubmit(String query)
                {
                    mSearchString = query;
                    //doFilterAsync(mSearchString);
                    toast.makeText(getApplicationContext(), "Test2", Toast.LENGTH_LONG).show();
    
                    return true;
                }
            };
    
            mSearchView.setOnQueryTextListener(queryTextListener);
        }
    
        return true;
    
    }
    
  • Joaquin Iurchuk
    Joaquin Iurchuk about 9 years
    Note that now you should import android.support.v7.widget.SearchView
  • Bala Vishnu
    Bala Vishnu over 8 years
    Thanks, any idea as how to handle the "Go" click? it would help
  • koesclem
    koesclem over 8 years
    I will just link the official documentation where you can also find how to react to the query developer.android.com/training/search/setup.html
  • DragonT
    DragonT over 8 years
    Note the app:actionViewClass instead of android:actionViewClass
  • Ravi Bhandari
    Ravi Bhandari over 8 years
    How can i return search result from SearchResultsActivity to MaiActivity?
  • Nick.D
    Nick.D over 8 years
    This answer is far more helpful if you don't want to create/move to a new activity when a user has submitted the search query. This will allow you to stay on the same activity/fragment and just update a view based on the users input. Great stuff.
  • Max
    Max about 8 years
    <action android:name="android.intent.action.VIEW" /> - is redundant? Working without it.
  • tm1701
    tm1701 about 8 years
    UserFeedback ... is my Toast-alike method.
  • Tarun
    Tarun over 7 years
    You should update your answer and add app:showAsAction="always|collapseActionView"
  • Saravanan
    Saravanan almost 7 years
    Keyboard input not taken in search view
  • Abandoned Cart
    Abandoned Cart about 6 years
    If you are using the support SearchView, don't forget to declare it as android.support.v7.widget.SearchView in the XML, too.
  • Ali
    Ali over 5 years
    don't forget to add in gradle implementation 'com.android.support:design:$latest_version'
  • IgorGanapolsky
    IgorGanapolsky about 5 years
    What is iconified?
  • IgorGanapolsky
    IgorGanapolsky about 5 years
    Why is menu necessary?
  • noe
    noe about 5 years
    ¨If you want the search field to always be visible, then call setIconifiedByDefault(false)¨ from the docs
  • Alston
    Alston over 4 years
    What's R.menu.main?
  • Daniil
    Daniil over 4 years
    If you've migrated to androidX use: androidx.appcompat.widget.SearchView
  • Amar Singh
    Amar Singh about 4 years
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { } you can directly call this method here you can infilate own menu, and handle this directoly from from fragment without using activity. nice thanks
  • Admin
    Admin over 2 years
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.