MaterialSearchBar is a beautiful and easy to use library will help to add Lollipop Material Design SearchView in your project.
Let’s look at the installation.
Installation
Add this code to the the project level build.gradle
file. We are registering the jitpack.io
as our repository under the repositories DSL.
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
- Then add the dependency to the the app level build.gradle file
implementation 'com.github.mancj:MaterialSearchBar:0.7.6'
Then in your layout add:
<com.mancj.materialsearchbar.MaterialSearchBar style="@style/MaterialSearchBarLight" app_mt_speechMode="true" app_mt_hint="Custom hint" app_mt_maxSuggestionsCount="10" android_layout_width="match_parent" android_layout_height="wrap_content" android_id="@+id/searchBar" />
Here’s a simple example:
private List<String> lastSearches; private MaterialSearchBar searchBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); searchBar = (MaterialSearchBar) findViewById(R.id.searchBar); searchBar.setHint("Custom hint"); searchBar.setSpeechMode(true); //enable searchbar callbacks searchBar.setOnSearchActionListener(this); //restore last queries from disk lastSearches = loadSearchSuggestionFromDisk(); searchBar.setLastSuggestions(list); //Inflate menu and setup OnMenuItemClickListener searchBar.inflateMenu(R.menu.main); searchBar.getMenu().setOnMenuItemClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); //save last queries to disk saveSearchSuggestionToDisk(searchBar.getLastSuggestions()); } @Override public void onSearchStateChanged(boolean enabled) { String s = enabled ? "enabled" : "disabled"; Toast.makeText(MainActivity.this, "Search " + s, Toast.LENGTH_SHORT).show(); } @Override public void onSearchConfirmed(CharSequence text) { startSearch(text.toString(), true, null, true); } @Override public void onButtonClicked(int buttonCode) { switch (buttonCode){ case MaterialSearchBar.BUTTON_NAVIGATION: drawer.openDrawer(Gravity.LEFT); break; case MaterialSearchBar.BUTTON_SPEECH: openVoiceRecognizer(); } }
You can find more examples here.
How MaterialSearchBar Works
Let’s examine in detail the internal details of MaterialSearchBar.
Internally MaterialSearchBar library has 4 public classes:
No. | Class | Role |
---|---|---|
1. | SuggestionsAdapter.java | A base class adapter for MaterialSearchBar.Can be used to customize the suggestionslist of MaterialSearchBar. |
2. | DefaultSuggestionsAdapter.java | Default adapter for suggestions. |
3. | SimpleOnSearchActionListener.java | Listens to Search state,search confirmation and search button click events |
4. | MaterialSearchBar.java | Used to search/filter. |
1. SuggestionsAdapter – How it Works
Here’s the role of this class:
No. | Role |
---|---|
1. | We use this class to customize the suggestion list of MaterialSearchBar. |
This class is defined in the com.mancj.materialsearchbar.adapter
package:
package com.mancj.materialsearchbar.adapter;
This class is an abstract class:
public abstract class SuggestionsAdapter<S, V extends RecyclerView.ViewHolder>..{}
And derives from RecyclerView.Adapter
:
public abstract class SuggestionsAdapter<S, V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>{}
In the above generic parameters, S
is the parameter type of your suggestions model while V
is the ViewHolder.
First and foremost, the SuggestionsAdapter
defines three internal fields:
- The first is an ArrayList for holding suggestions.This ArrayList is privately instantiated.
- The second is a private declaration of Layout Inflater class. This LayoutInflater object will hold a LayoutInflater instance that will be passed as a parameter via the Constructor.
- The last is a protected Integer which sets the maximum suggestions count to
5
.
######## Creating SuggestionsAdapter.
The SuggestionsAdapter is an abstract class and can be created by inheriting from it and passing a LayoutInflater instance via the super call.
public class MySuggestionsAdapter extends SuggestionsAdapter<String, MySuggestionsAdapter.SuggestionHolder> { public MySuggestionsAdapter(LayoutInflater inflater) { super(inflater); } .... }
SuggestionsAdapter Mutation methods.
These are methods for manipulating suggestions like adding, setting, deleting and clearing.
No. | Method | Responsibility |
---|---|---|
1. | addSuggestion(S r) |
Where S is the type of suggestion model.This method will add the Suggestion into Suggestions list and call notifyDatasetChanged() . |
2. | setSuggestions(List<S> suggestions) |
This method will set the passed list as our Suggestions List and call notifyDatasetChanged() . |
3. | deleteSuggestion(int postion, S r) |
This method will delete the passed suggestion and call notifyItemRemoved(postion) . |
4. | clearSuggestions() |
This method will clear all the suggestions and call notifyDataSetChanged() . |
SuggestionsAdapter Configuration Methods.
No. | Method | Responsibility |
---|---|---|
1. | setMaxSuggestionsCount(int maxSuggestionsCount) |
Sets the maximum suggestions integer to our private maxSggestionsCount variable. |
2. | int getMaxSuggestionsCount() |
Retrieves the maxSggestionsCount value. |
3. | LayoutInflater getLayoutInflater() |
Protected method to retrieve the LayoutInflater field. |
4. | int getSingleViewHeight() |
An abstract method to return the height of a single view item in the list.All view items must have same height. |
5. | int getListHeight() |
This method calculates the total height of the lists displayed: getItemCount() * getSingleViewHeight() |
SuggestionsAdapter click events
SuggestionsAdapter remember is basically RecyclerView.Adapter and takes a RecyclerView.ViewHolder as a generic parameter.
It therefore internally first override recyclerview.adapter methods.
Then defines an interface to hold our Click event signatures:
No. | Method |
---|---|
1. | OnItemClickListener(int position,View v) |
2. | OnItemDeleteListener(int position,View v) |
2. DefaultSuggestionAdapter
This is also defined in the adapter package:
package com.mancj.materialsearchbar.adapter;
This is a class concrete class:
public class DefaultSuggestionsAdapter..{}
That is basically a child of the SuggestionsAdapter:
public class DefaultSuggestionsAdapter extends SuggestionsAdapter<String, DefaultSuggestionsAdapter.SuggestionHolder> { }
Creating DefaultSuggestionsAdapter
We create this class by instantiating and passing in a LayoutInflater object, then invoke the super contructor method of the parent SuggestionsAdapter class:
public DefaultSuggestionsAdapter(LayoutInflater inflater) { super(inflater); }
Mutation and Configuration Methods
This class basically inherits the Mutation anc Configuration methods defined in the parent SuggestionsAdapter class.
SuggestionsHolder
DefaultSuggestionsAdapter defines an inner SuggestionsHolder
class which is basically a Recycler.ViewHolder class.
The SuggestionsHolder contains a TextView and an ImageView for deleting the text.
It then listens to the TextView click and Delete ImageView click events.
3. SimpleOnSearchActionListener
This class is defined in the package com.mancj.materialsearchbar
:
package com.mancj.materialsearchbar;
It is an abstract class;
public abstract class SimpleOnSearchActionListener..{}
That implements MaterialSearchBar.OnSearchActionListener
interface:
public abstract class SimpleOnSearchActionListener implements MaterialSearchBar.OnSearchActionListener {}
This class overrides three methods:
@Override public void onSearchStateChanged(boolean enabled) { } @Override public void onSearchConfirmed(CharSequence text) { } @Override public void onButtonClicked(int buttonCode) { }
4. MaterialSearchBar class
MaterialSearchBar is a class that derives from RelativeLayout.
public class MaterialSearchBar extends RelativeLayout..{}
MaterialSearchBar implements several interfaces:
public class MaterialSearchBar extends RelativeLayout implements View.OnClickListener, Animation.AnimationListener, SuggestionsAdapter.OnItemViewClickListener, View.OnFocusChangeListener, TextView.OnEditorActionListener {}
Creating MaterialSearchBar
MaterialSearchBar defines three public constructor methods for it’s creation:
No. | Method | Responsibility |
---|---|---|
1. | MaterialSearchBar(Context context, AttributeSet attrs) |
|
2. | MaterialSearchBar(Context context, AttributeSet attrs, int defStyleAttr) |
|
3. | MaterialSearchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) For use in LOLLIPOP and above. |
All these contructor methods internally call the super class constructor.
They then call an internal init()
method which does several functions among the following:
No. | Role |
---|---|
1. | First Inflate the searchbar layout. |
2. | Create a TypedArray that using the Context obtains MaterialSearchBar styles. |
3. | Then obtain the various attributes from that TypedArray and assign them to instance fields like searchIcon Resource ID,navIcon Resource ID, hint String,placeholder Text,maxSuggestionsCount int,speechMode boolean, hint color,text color and navButtonEnabled boolean. |
4. | It will then check if the SuggestionsAdapter is null and if so instantiate the DefaultSuggetionsAdapter. |
5. | It will set the Click Listener of this adapter to the instance of this class. |
6. | It will then set the maximum suggestions count to what was obtained from the resource. |
7. | It will create an internal RecyclerView and set our defaultSuggestionsAdapter as its adapter and LinearLayoutManager as the LayoutManager. |
8. | Then several widgets used by the MaterialSearchBar will be referenced by their IDs. These include the searchIcon ImageView, arrowIcon Imagevoew, searchEdit editText, placeHolder textView, inputContainer LinearLayout and navIcon n ImageView. |
9. | OnClick Listeners will then be set to the arrowIcon, navIcon and searchIcon as this . |
10. | Then FocusChangeListener and EditorActionListener will be set on searchEditText. |
MaterialSearchBar Menus
MaterialSearchBars can have menus. The MaterialSearchBar
class defines a public method that allows us simply pass the menu resource to be inflated.
void inflateMenu(int menuResource)
What happens internally is that if the menu resource is found, first we’ll reference a menuIcon imageview, set it’s parameters and set it as visible.
Then an onClickListner event listener will be attached to it.
If clicked we’ll instantiate a PopupMenu, passing in the Context and menuIcon, inflate the popupMenu from menuResource and set it to Gravity.Right
.
To get the menu you simply call getMenu()
which returns the PopupMenu.
Enabling and Disabling Search
MaterialSearchBar allows us enable and disable search.
These can simply be done by calls to methods:
enableSearch()
– To enable search.disableSearch()
– To disable search.
Let’s see how these work under the hood:
Enabling Search
Enabling Search basically means showing search input edittext and close arrow icon.
The first thing that happens when the enableSearch()
is invoked is that adapter.NotifyDataSetChanged()
is called to refresh the SuggestionsAdapter.
Then a searchEnabled
instance private variable is set to true
. This is important because that variable is used by several methods to determine whether search is enabled or not.
Then two animations are loaded, fade in left and fade out left.And an AnimationListener event is set to fade in left animation.
The placeHolder is then hidden and instead the inputContainer is set visible. The fade in left animation is set to the inputContainer.
Disabling Search.
Disabling search is hiding the search input and closing the arrow.
For disabling search we do the roughly the opposite of the enableSearch
.
First we set searchEnabled
to false. Load the two animations.
Then set the AnimationLister on fade out left.
Then set the searchIcon to visible.
Set the fade out animation to the inputContainer.
Showing, Hiding and Clearing Suggestions Lists.
No. | Method | Description |
---|---|---|
1. | showSuggestionsList() |
Shows suggestions list with animations. |
2. | hideSuggestionsList() |
Shows suggestions list with animations. |
2. | clearSuggestions() |
Clears suggestions with animations.Also clears them in the SuggestionsAdapter. |
Public Methods
Here are some public methods for MaterialSearchBar:
- addTextChangeListener(TextWatcher textWatcher)
- clearSuggestions()
- disableSearch()
- enableSearch()
- getLastSuggestions()
- getMenu()
- getText()
- hideSuggestionList()
- inflateMenu(int menuResource)
- inflateMenu(int menuResource, int icon)
- isSearchEnabled()
- isSpeechModeEnabled()
- isSuggestionsVisible()
- setArrowIcon(int arrowIconResId)
- setArrowIconTint(int arrowIconTint)
- setCardViewElevation(int elevation)
- setClearIcon(int clearIconResId)
- setClearIconTint(int clearIconTint)
- setCustomSuggestionAdapter(SuggestionsAdapter suggestionAdapter)
- setDividerColor(int dividerColor)
- setHint(CharSequence hintText)
- setIconRippleStyle(boolean borderlessRippleEnabled)
- setLastSuggestions(List suggestions)
- setMaxSuggestionCount(int maxSuggestionsCount)
- setMenuDividerEnabled(boolean menuDividerEnabled)
- setMenuIcon(int menuIconResId)
- setMenuIconTint(int menuIconTint)
- setNavButtonEnabled(boolean navButtonEnabled)
- setNavIconTint(int navIconTint)
- setOnSearchActionListener(OnSearchActionListener 31.
- onSearchActionListener)
- setPlaceHolder(CharSequence placeholder)
- setPlaceHolderColor(int placeholderColor)
- setRoundedSearchBarEnabled(boolean roundedSearchBarEnabled)
- setSearchIcon(int searchIconResId)
- setSearchIconTint(int searchIconTint)
- setSpeechModeEnabled(boolean speechMode)
- setSuggestionsClickListener(SuggestionsAdapter.OnItemViewClickListener listener)
- setText(String text)
- setTextColor(int textColor)
- setTextHighlightColor(int highlightedTextColor)
- setTextHintColor(int hintColor)
- showSuggestions()
- updateLastSuggestions(List suggestions)
Find a complete example here.