So in this Xamarin.Android series, we look at a searchview exmple with a recyclerview. Our recyclerview will render a large list of cardviews. We want to give our users the ability to search filter data dynamically in realtime.
The ability to search filter data is especially important in mobile devices given the limited screen size. A mobile device can probably only show about a 5-10 list items in a given viewport. What about if you have hundreds of list items? You don’t want your users scrolling through all that data looking for something.
A search filter can do wonders for them. We don’t use any third party library in this tutorial. We only use a Recyclerview, a searchview and a cardview.
Screenshot
- Here’s the screenshot of the project.
Xamarin Android RecyclerView example.
- Project Structure
Common Questions this example explores
- Xamarin Android RecyclerView SearchView example.
- Search Filter data in a recylcerview in xamarin android.
- Xamarin RecyclerView with Search filter list of cardviews.
Tools Used
This example was written with the following tools:
- Windows 8
- Visual Studio IDE
- Genymotion Emulator
- Language : C#
- Topic: Xamarin.Android RecyclerView Search Filter,Xamarin.Android Search CardViews
- Platform : Xamarin Android
Source Code
Lets jump directly to the source code.
MyAdapter.cs
- Our MyAdapter class.
- Derives from RecyclerView.Adapter
- Implements Android.Widget.IFilterable interface
- We inflate our custom layout here and bind data to resulting view
- Also includes internal ViewHolder class
using System;
using Android.Runtime;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
namespace Recycler_Search
{
class MyAdapter : RecyclerView.Adapter,IFilterable
{
private JavaList<String> galaxies;
private readonly JavaList<String> currentList;
public MyAdapter(JavaList<String> galaxies)
{
this.galaxies = galaxies;
this.currentList = galaxies;
}
//BIND DATA TO VIEWS
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
MyViewHolder h = holder as MyViewHolder;
if (h != null) h.NameTxt.Text = galaxies[position];
}
//INITIALIZE VH
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
//INFLATE LAYOUT TO VIEW
View v = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.Model, parent, false);
MyViewHolder holder = new MyViewHolder(v);
return holder;
}
//TOTAL NUM OF TVSHOWS
public override int ItemCount
{
get { return galaxies.Size(); }
}
public void setGalaxies(JavaList<String> filteredGalaxies)
{
this.galaxies = filteredGalaxies;
}
public Filter Filter
{
get { return FilterHelper.newInstance(currentList, this); }
}
/*
* Our ViewHolder class
*/
internal class MyViewHolder : RecyclerView.ViewHolder
{
public TextView NameTxt;
public MyViewHolder(View itemView)
: base(itemView)
{
NameTxt = itemView.FindViewById<TextView>(Resource.Id.nameTxt);
}
}
}
}
FilterHelper.cs
- Our FilterHelper class.
- Derives from android.widget.filter
- Responsible for performing filtering and publishing results back to the adapter.
using Android.Runtime;
using Android.Widget;
using Java.Lang;
using String = System.String;
namespace Recycler_Search
{
class FilterHelper : Filter
{
static JavaList<String> currentList;
static MyAdapter adapter;
public static FilterHelper newInstance(JavaList<String> currentList, MyAdapter adapter)
{
FilterHelper.adapter = adapter;
FilterHelper.currentList = currentList;
return new FilterHelper();
}
/*
- Perform actual filtering.
*/
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
FilterResults filterResults=new FilterResults();
if (constraint != null && constraint.Length() > 0)
{
//CHANGE TO UPPER
//constraint = constraint.ToString().ToUpper();
string query = constraint.ToString().ToUpper();
//HOLD FILTERS WE FIND
JavaList<String> foundFilters=new JavaList<String>();
//ITERATE CURRENT LIST
for (int i=0;i<currentList.Size();i++)
{
string galaxy = currentList[i];
//SEARCH
if (galaxy.ToUpper().Contains(query.ToString()))
{
//ADD IF FOUND
foundFilters.Add(galaxy);
}
}
//SET RESULTS TO FILTER LIST
filterResults.Count=foundFilters.Size();
filterResults.Values=foundFilters;
}else
{
//NO ITEM FOUND.LIST REMAINS INTACT
filterResults.Count=currentList.Size();
filterResults.Values=currentList;
}
//RETURN RESULTS
return filterResults;
}
/*
* Publish results to UI.
*/
protected override void PublishResults(ICharSequence constraint, FilterResults results)
{
adapter.setGalaxies((JavaList<String>)results.Values);
adapter.NotifyDataSetChanged();
}
}
}
MainActivity.cs
- Our MainActivity class.
- We override our activity’s onCreate() method here.
- We initialize searchview,recyclerview and MyAdapter classes
- We handle onQueryTextChange event and call InVokeFilter method of our adapter
- We also define our data source here.
using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.Widget;
using SearchView = Android.Widget.SearchView;
namespace Recycler_Search
{
[Activity(Label = "Recycler_Search", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
private SearchView sv;
private RecyclerView rv;
private MyAdapter adapter;
/*
* When activity is created
*/
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
sv = FindViewById<SearchView>(Resource.Id.sv);
//RV
rv = FindViewById<RecyclerView>(Resource.Id.mRecylcerID);
rv.SetLayoutManager(new LinearLayoutManager(this));
rv.SetItemAnimator(new DefaultItemAnimator());
//ADAPTER
adapter = new MyAdapter(getGalaxies());
rv.SetAdapter(adapter);
//EVENTS
sv.QueryTextChange += sv_QueryTextChange;
}
/*
* When user types on searchview
*/
void sv_QueryTextChange(object sender, SearchView.QueryTextChangeEventArgs e)
{
//FILTER
adapter.Filter.InvokeFilter(e.NewText);
}
/*
* Our data source.
* Returns Android.Runtime.JavaList
*/
public static JavaList<String> getGalaxies()
{
JavaList<String> galaxies = new JavaList<String>
{
"StarBust",
"Pinwheel",
"IC 1011",
"Sombrero",
"Virgo Stellar Stream",
"Canis Majos",
"Cartwheel",
"Ring Nebula",
"Centaurus A",
"Own Nebula",
"Large Magellonic Cloud",
"Small Magellonic Cloud",
"MilkyWay",
"Andromeda",
"Messier 81",
"Leo",
"Hoag's Object",
"Mayall's Object",
"Messier 87",
"Whirlpool",
"Triangulumn"
};
return galaxies;
}
}
}
Main.axml
- Content Layout.
- Defines the views and widgets to be displayed inside the MainActivity.
- In this case a RecyclerView and a searchview.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#009968"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SearchView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/sv" />
<android.support.v7.widget.RecyclerView
android:id="@+id/mRecylcerID"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Model.axml
- Model Layout.
- Contains a CardView with textviews.
- Will be inflated to a viewitem for our RecyclerView.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="5dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ffffff">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#333333"
android:text="Caption"
android:id="@+id/nameTxt"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="4dp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Video Tutorial
- Video version of this tutorial.
https://www.youtube.com/watch?v=FTrEFDv2Njc
Download the Project below:—-Coming soon.
Download
How To Run
- Download the project above.
- You’ll get a zipped file,extract it.
- Open the Visual Studio.
- Now close, already open project.
- From the Menu bar click on File >Open> Project/Solution.
- That’s it.
Conclusion.
We saw a simple xamarin android recyclerview and searchview example: how to search filter data in a recyclerview.
More
YouTube
- Visit our channel for more examples like these.
- Lets share tips and ideas in our Facebook Page.
Oclemy,Cheers.