Welcome to this post.
Android Material Search view tutorial. In this tutorial, we going to make a project and Implement A search view on the toolbar.
For search view, I use a 3rd party library
Material SearchView
Note: If you don't want to use 3rd party library see this post,
Android Material SearchView with Recent Search Suggestions
Let's start-
Before starting, see a screenshot-
|
Material Search View |
we have to do with this project-
1. we set search view on the toolbar.
2. Filter RecyclerView with text input
3. voice search
some bonus- In this project,
1. use SQL database for store data2. use the content provider to access data.
3. use Loaders for load data(Curser loaders).
Let's Start- First, add this line to your build.gradle file and sync gradle.
compile 'br.com.mauker.materialsearchview:materialsearchview:1.2.2'
Now go to on your style.xml file and below style-
<style name="MaterialSearchViewStyle">
<item name="searchBackground">@color/white_ish</item>
<item name="searchVoiceIcon">@drawable/ic_action_voice_search</item>
<item name="searchCloseIcon">@drawable/ic_action_navigation_close</item>
<item name="searchBackIcon">@drawable/ic_action_navigation_arrow_back</item>
<item name="searchSuggestionBackground">@color/search_layover_bg</item>
<item name="searchBarHeight">?attr/actionBarSize</item>
<item name="voiceHintPrompt">@string/hint_prompt</item>
<item name="android:textColor">@color/black</item>
<item name="android:textColorHint">@color/gray_50</item>
<item name="android:hint">@string/search_hint</item>
<item name="android:inputType">textCapWords</item>
</style>
OK, now time to add a toolbar to the layout. In this case, I add on activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
tools:context=".MainActivity"
android:background="@color/colorPrimary"
android:layout_marginBottom="2dp"
android:elevation="6dp">
<!-- don't forget to set elevation or it look like old action bar-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<br.com.mauker.materialsearchview.MaterialSearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/MaterialSearchViewStyle"/>
</RelativeLayout>
Note: I will provide GitHub link to this project later in this post
Now add a menu button on menu.xml-
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:orderInCategory="100"
android:title="@string/abc_search_hint"
app:showAsAction="always" />
options menu looks like:
|
Material Search View (options menu) |
Now time to write java code- In this case MainActivity.java
MaterialSearchView searchView;
and again this view on onCreate-
searchView = (MaterialSearchView) findViewById(R.id.search_view);
now set all search operation I created a private method and call it on Oncreate-
In this method, we add three listeners to the search view-
1. setOnQueryTextListener
2. setSearchViewListener
3. setOnVoiceClickedListener In listener
1. setOnQueryTextListener is fired when we type text in the search view. In this listener, we have to override two methods name-
i. onQueryTextSubmit
ii. onQueryTextChange
i.
onQueryTextSubmit is called when we put the query data with submit button.
after submit-
* build a URI
* call getContentResolver and query database and save it on cursor variable.
* if the cursor is not null and cursor data is more than 0 we have data(Call cursor.getCount())
* so we go to the details activity with intent and set this URI with intent
*close search view
ii.
onQueryTextChange is called every time when you write.
So we have to set-
* we are going to update recycler view with type text
* we check the text length is greater than zero
* then we create a selection string variable for cursor query. we use SQL LIKE statement not where statement.
String selection = MainWordDBContract.Entry.COLUMN_WORD +" like ? ";
* add also selection Argument-
String[] selectionArg = new String[]{newText+"%"};
* same way to get cursor and same condition for update UI as onQueryTextSubmit
Let's see the code-
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Uri uri = MainWordDBContract.Entry.buildUriWithWord(query.toUpperCase());
Cursor cursor = getContentResolver().query(uri,
MainActivity.projection,null,null,null);
if (cursor != null && cursor.getCount() > 0){
Intent intent = new Intent(MainActivity.this,
DetailsActivity.class);
intent.setData(uri);
startActivity(intent);
searchView.closeSearch();
searchView.setCloseOnTintClick(false);
}
if (cursor != null){
cursor.close();
}
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
if (newText.length() > 0){
String selection = MainWordDBContract.Entry.COLUMN_WORD +" like ? ";
//if you are try to search from any position of word
//then use
//String[] selectionArg = new String[]{"%"+newText+"%"};
//if you try to search from start of word the use this line
String[] selectionArg = new String[]{newText+"%"};
Cursor cursor = getContentResolver().query(MainWordDBContract.Entry.CONTENT_URI,
MainActivity.projection,selection,selectionArg,null);
if (cursor != null && cursor.getCount() > 0){
mAdapter.swapCursor(cursor);
}
return true;
} else {
return false;
}
}
});
Now add the setSearchViewListener listener and there are also two methods.
* if search view is open then hide the fab
* if searchView close the show the fab again Code-
searchView.setSearchViewListener(new MaterialSearchView.SearchViewListener() {
@Override
public void onSearchViewOpened() {
fab.hide();
}
@Override
public void onSearchViewClosed() {
fab.show();
}
});
On the last, we have added setOnVoiceClickedListener if you are using this option. for this, I write another method name askSpeechInput so let's see the code one by one- the listener-
searchView.setOnVoiceClickedListener(new MaterialSearchView.OnVoiceClickedListener() {
@Override
public void onVoiceClicked() {
askSpeechInput();
}
});
method-
private void askSpeechInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
"Speak your desire word");
try {
startActivityForResult(intent, MaterialSearchView.REQUEST_VOICE);
} catch (ActivityNotFoundException a) {
a.printStackTrace();
slet("Activity not found", a);
Toast.makeText(this, "Sorry Speech To Text is not " +
"supported in your device", Toast.LENGTH_SHORT).show();
}
}
one more method to go. we are now overriding onActivityResult for getting voice input-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MaterialSearchView.REQUEST_VOICE && resultCode == RESULT_OK) {
ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (matches != null && matches.size() > 0) {
String searchWrd = matches.get(0);
if (!TextUtils.isEmpty(searchWrd)) {
//Todo more accure on settings
searchView.setQuery(searchWrd, false);
Uri uri = MainWordDBContract.Entry.buildUriWithWord(searchWrd.toUpperCase());
Cursor cursor = getContentResolver().query(uri,
MainActivity.projection,null,null,null);
if (cursor != null && cursor.getCount() > 0){
Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
intent.setData(uri);
startActivity(intent);
searchView.closeSearch();
searchView.setCloseOnTintClick(false);
}
if (cursor != null){
cursor.close();
}
}
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
voice search screen short:
|
Material Search View (voice search) |
add this line onResume method
searchView.activityResumed();
and last one-
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case R.id.action_search:
// Open the search view on the menu item click.
searchView.openSearch();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Now run your app and see the material search view
It will work fine.
Note: If you don't want to use 3rd party library to add search functionality, see this post.
Android Material SearchView with Recent Search Suggestions
Thank you for reading
Happy coding