Android MaterialSearchBar

| Page Views: 469

MaterialSearchBar is a beautiful and easy to use library will help to add Lollipop Material Design SearchView in your project.

Android MaterialSearchBar

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:

  1. The first is an ArrayList for holding suggestions.This ArrayList is privately instantiated.
  2. 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.
  3. 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:

  1. enableSearch() - To enable search.
  2. 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:

  1. addTextChangeListener(TextWatcher textWatcher)
  2. clearSuggestions()
  3. disableSearch()
  4. enableSearch()
  5. getLastSuggestions()
  6. getMenu()
  7. getText()
  8. hideSuggestionList()
  9. inflateMenu(int menuResource)
  10. inflateMenu(int menuResource, int icon)
  11. isSearchEnabled()
  12. isSpeechModeEnabled()
  13. isSuggestionsVisible()
  14. setArrowIcon(int arrowIconResId)
  15. setArrowIconTint(int arrowIconTint)
  16. setCardViewElevation(int elevation)
  17. setClearIcon(int clearIconResId)
  18. setClearIconTint(int clearIconTint)
  19. setCustomSuggestionAdapter(SuggestionsAdapter suggestionAdapter)
  20. setDividerColor(int dividerColor)
  21. setHint(CharSequence hintText)
  22. setIconRippleStyle(boolean borderlessRippleEnabled)
  23. setLastSuggestions(List suggestions)
  24. setMaxSuggestionCount(int maxSuggestionsCount)
  25. setMenuDividerEnabled(boolean menuDividerEnabled)
  26. setMenuIcon(int menuIconResId)
  27. setMenuIconTint(int menuIconTint)
  28. setNavButtonEnabled(boolean navButtonEnabled)
  29. setNavIconTint(int navIconTint)
  30. setOnSearchActionListener(OnSearchActionListener 31.
  31. onSearchActionListener)
  32. setPlaceHolder(CharSequence placeholder)
  33. setPlaceHolderColor(int placeholderColor)
  34. setRoundedSearchBarEnabled(boolean roundedSearchBarEnabled)
  35. setSearchIcon(int searchIconResId)
  36. setSearchIconTint(int searchIconTint)
  37. setSpeechModeEnabled(boolean speechMode)
  38. setSuggestionsClickListener(SuggestionsAdapter.OnItemViewClickListener listener)
  39. setText(String text)
  40. setTextColor(int textColor)
  41. setTextHighlightColor(int highlightedTextColor)
  42. setTextHintColor(int hintColor)
  43. showSuggestions()
  44. updateLastSuggestions(List suggestions)

Find a complete example here.

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section.

About Me.

After completing his Software Engineering bachelors program, Oclemy(Clement Ochieng) these days is a man of two lives. At day he works for a startup in Nairobi, Kenya. At night he works tirelessly on building ProgrammingWizards TV, a tv channel for student coders and this website to help share the source code. In between he practices Meditation and Self actualization to help him keep balance. He also likes going for long solo walks to connect more with nature.




Recommendations


What do You Think


Previous Post Next Post