Xamarin.Android S1E7 : RecyclerView – Search/Filter

Xamarin.Android S1E7 : RecyclerView – Search/Filter







Introduction

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.

Xamarin Android Recyclerview Search Filter example

  • Project Structure

Xamarin Android Recyclerview Search Filter example

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.csFilterHelper.csMainActivity.csMain.axmlModel.axmlVideo TutorialDownload
-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);
            }
        }
    }
}

 

  • 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();
        }
    }
}

 

  • 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;
        }
    }
}

 

  • 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 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 version of this tutorial.

Xamarin.Android S1E7 : RecyclerView - Search/Filter

  • Download the Project below:----Coming soon.
Download

How To Run

  1. Download the project above.
  2. You'll get a zipped file,extract it.
  3. Open the Visual Studio.
  4. Now close, already open project.
  5. From the Menu bar click on File >Open> Project/Solution.
  6. 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.

Facebook

Oclemy,Cheers.



Rating :

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    eight − five =

    COMMENTS