Implement Custom SearchView

I recently had to implement a SearchView with filtering kind of like the one in Google’s Gmail and Inbox app. Since this seemed standard in apps that follow the material design guidelines, I thought it would be simple to implement. Oh how wrong I was.

For the impatient, before we get too deep into the post, the repo for this recipe is at https://github.com/chrisjeon/CustomSearchViewRecipe

Implementing this SearchView was one of the most frustrating and nightmarish experience I’ve ever come across in my programming career. The main reason this SearchView is so difficult to implement using standard Android APIs is that Google’s documentation in general is just downright terrible. When I say downright terrible, I mean that the code sample that they give flat out doesn’t work work, give conflicting information, and sometimes they flat out forget to mention things. Googling through your way doesn’t work either since the information on how to implement and style the SearchView correctly is split and spread throughout various blog posts and StackOverflow posts throughout the internet. Maybe this problem of bad documentation in the Android world will be a topic for another blog post.

With that said, let’s continue onto the main topic of the post, implementing a SearchView in an easy to understand manner. when I talk about a SearchView, I’m talking about the SearchFilter thing found in Google’s Gmail and Inbox Apps like this.

And when you type stuff into it, it should search and filter based on the data available in the API you’re querying and display something like below.

Note that the above is only an example. The code recipe we’re going to be putting together will be flexible enough so that the filter view in the above screenshot can have user images, other information, and etc that you need to display in your app. To build this in an easy way, we’re going to be leveraging various third party libraries to cobble this solution together. These libraries are:

The explanations for both libraries are below

MaterialSearchView (https://github.com/MiguelCatalan/MaterialSearchView)

This is just a third party library to quickly implement a Material SearchView without going through and hoops that Google presents in front of you if you try to implement it going through the Google Docs. All you have to do is insert a layout provided by the library, add some bindings in your Activity, and boom, you’re good to go. The library comes with standard dropdown filtering so if that is all you need, just plug this library in and you should be good to go without having to read the rest of this tutorial.

SugarORM (http://satyan.github.io/sugar/)

This is the simplest ORM I could find for Android. I heard that SugarORM lacks in the performance department, but it was the easiest for me to set up. Obviously, if you have experience with other Android ORMs, you’re free to replace SugarORM with those, but the repo I’m uploading with this will be using SugarORM.

Adding the User model

We’ll be adding a User as a POJO in the codebase. You can add whatever you want, but in our search filter results, we’ll be filtering through various Users. This is what our User class looks like extending from the SugarRecord so that we can apply SugarORM’s methods on the User model so we can cache and retrieve User data from the SQLite database.

Second, in our MainActivity, we want to create fake users and save them into the database. If you’re retrieving user info from an API, you want to make the appropriate API calls. This recipe is just an example, so I’m creating fake users and saving them in the database. Also, do note that I’m deleting all users in the database before I save them. We can certainly put uniqueness constraints in the database to figure out which records to save, update, avoid, and etc to avoid having duplicate data in the databse, but for the sake of simplicity, I’m bulk deleting all users and bulk saving users in the database. Notice I don’t save the users one by one for performance reasons.

Adding the Search Icon

First thing we want to do is add the search menu icon in the toolbar. This should be relatively straightforward to do. In the menu, add the search_item icon like this

After that, hook it up in your MainActivity.java like this

Notice that if the user clicks the “search_item” button, we simply start up a new activity called SearchResultsActivity. This is so that we can have a custom xml layout we can modify to our liking to have those custom search filters in the screenshots posted above.

The SearchResultsActivity

The SearchResultsActivity is where all the magic happens. I did notice that the MaterialSearchView library had some bugs, so I had to add custom listeners and behaviors in this SearchResultsActivity to make the library behave appropriately. The code for the SearchResultsActivity is below

This SearchResultsActivity displays the activity_search_results.xml, which looks like the below

All the above layout does is display the MaterialSearchView library and two recycler views, one for showing the search history and second for the search results. The MaterialSearchView library is activated in the onCreate method of the SearchResultsActivity so that from the UX perspective, the entire SearchResultsActivity is for searching through the users. For the “recycler_search_history” recycler view, we simply display the previously submitted users and for the “recycler_search_results” recycler view, we filter through the users in the database as the user emails are typed into the SearchView.

Displaying previously searched users

In the SearchResultsActivity, when the user hits submit in the search bar, we save the user’s email address into the database. The code for that in the SearchResultsActivity.java is this part

When the user hits “submit”, we instantiate a new SearchHistory model which looks like this

and then save that in the database. Notice that when the SearchResultsActivity starts up, we load up all of the SearchHistory’s in the database and load them up in the SearchHistory adapter.

And finally where the magic for the user filtering happens.

As the user types new text into the SearchView, we take that text, and do your average sql LIKE query to get the users that match the conditions. For this recipe, we’re just querying for users with similar emails, but you can go crazy as you want with the queries and various conditions as for which users to filter by. After we load up the users, we simply set it in the appropriate recycler view adapter to display the user results in the layout.

One reason we’re pulling the users out of the database rather than making API calls is that making constant API calls as the user types into the SearchView is really bad for performance. This is the reason we’re utilizing an ORM to cache the data that we want to query by. In reality, you could also do where you query for the data first, and if there aren’t any valid results, then make an API call to see if any data on the server matches what the user is typing on the SearchView. This will lighten the load on performance hits and will probably keep the app usable, but I avoided that in the recipe for simplicity sake.

And with this, you get a result that looks like this while the user types

Do note that you can modify the SearchView prefilter however you want by modifying activity_search_results.xml.

Conclusion and a plea to the Android team

This post was written to hopefully make implementing SearchView’s with custom filtering views easier for other Android devs. It also probably didn’t need to have been written if the Android docs from Google were somewhat usable. So I plea to the Android team at Google to please please please improve your docs. Thousands of developer hours could be saved if the docs were easy to follow, correct, and well organized for devs to use.

About the Author Chris Jeon

Software developer currently focusing on Android development.