Pages

Implementing live search with SearchView + Action bar (Android)

What is live search? instant filtering of content as user types the search text in the search input field. Example: name search in phone's contact list.

This example is not a complete implementation of live search. It will give you the implementation details upto the part where you will get a instant callbacks (with search query) as user enters text in the search field. In the callback, usually, you filter the content with the passed search query and update the content view. For brevity sake I will leave that part to you to implement.

Before starting make sure, in app/build.gradle, minSdkVersion is 15 or higher.

Step 1: Declare string resources search_title and search_hint.

res/values/strings.xml
1
2
3
4
5
6
7
8
9
<resources>
    <string name="app_name">LiveSearchDemo</string>

    <string name="queryMessage">Search something</string>
    <string name="action_settings">Settings</string>
    
    <string name="search_title">Search</string>
    <string name="search_hint">Search hint</string>
</resources>

Step 2: Declare activity layout. In this demo we will use queryTextView to display the search term entered and if you click the button it will stop the live search.

res/layout/activity_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView android:id="@+id/queryTextView" android:text="@string/queryMessage" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop search"
        android:id="@+id/button"
        android:layout_below="@+id/queryTextView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="53dp"
        android:onClick="stopSearch" />

</RelativeLayout>

Step 3: Add SearchView to the action bar.

res/menu/menu_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<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=".MainActivity">

    <item android:id="@+id/search"
        android:title="@string/search_title"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

Step 4: Load action bar and set live search callback and other options. Make sure you are importing the right SearchView.

MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    MenuItem searchItem;
    SearchView searchView;
    TextView queryTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        queryTextView = (TextView) findViewById(R.id.queryTextView);
    }

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

        searchItem = menu.findItem(R.id.search);

        searchView = (SearchView) searchItem.getActionView();

        // default keyboard is not live search friendly. it displays a search 
        // icon which indicates it will start a search. We don't want that.
        // The IME_NULL will make the keyboard to display Done button instead which I
        // think can be interpeted as: You are done with search.
        searchView.setImeOptions(EditorInfo.IME_NULL);

        // apply search hint to display when search is started.
        searchView.setQueryHint(getResources().getString(R.string.search_hint));

        // set live search callback
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                // when done button in keyboard is pressed onQueryTextSubmit method is called
                searchItem.collapseActionView();

                return true;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                // this is where you filter your content
                queryTextView.setText("search query: " + s);

                return true;
            }
        });

        return true;
    }

    // use this when you want to stop live searching
    public void stopSearch (View view) {
        // collapseActionView() will remove the keyboard from screen and collapse the search field
        searchItem.collapseActionView();
    }
}

That's it. Happy coding. Cheers.