Forum Xamarin.Android

filter listview with SearchView

monemdcmonemdc Member ✭✭✭

hi

Fill in listView with names and photos from contacts .
With the following code, how to search and filter when using the previous code .

`//public

public static List contactList;
//

void FillContacts()
{

        var uri = ContactsContract.CommonDataKinds.Phone.ContentUri;

        string[] projection = {
            ContactsContract.Contacts.InterfaceConsts.Id,
            ContactsContract.Contacts.InterfaceConsts.DisplayName
            ContactsContract.Contacts.InterfaceConsts.PhotoId

        };


        var loader = new CursorLoader(activity, uri, projection, null, null, null);
        var cursor = (ICursor)loader.LoadInBackground();


        contactList = new List<STRING>();

        if (cursor.MoveToFirst())
        {
            do
            {
                contactList.Add(new STRING
                {
                    Id = cursor.GetLong(cursor.GetColumnIndex(projection[0])),
                    DisplayName = cursor.GetString(cursor.GetColumnIndex(projection[1])),
                    PhotoId = cursor.GetString(cursor.GetColumnIndex(projection[3]))
                });
            } while (cursor.MoveToNext());
        }
    }`
Tagged:

Best Answer

  • LandLuLandLu Xamurai
    edited March 27 Accepted Answer

    Define a custom filter and consume it in your adapter like:

    Filter filter;
    public override Filter Filter 
    {
        get 
        {
            if (filter == null)
            {
                filter = new CustomFilter(this);
            }
            return filter;
        } 
    }
    
    class CustomFilter : Filter
    {
        MyAdapter adapter;
        public CustomFilter(MyAdapter adapter)
        {
            this.adapter = adapter;
        }
        protected override FilterResults PerformFiltering(ICharSequence constraint)
        {
            FilterResults results = new FilterResults();
            string prefix = constraint.ToString().ToLower();
    
            if (prefix == null || prefix.Length == 0)
            {
                results.Values = FromArray(adapter.original.ToArray());
                results.Count = adapter.original.Count();
            }
            else
            {
                var values = adapter.original.Where(x => x.DisplayName.Contains(prefix)).ToArray();
                results.Values = FromArray(values);
                results.Count = values.Count();
            }
            return results;
        }
    
        protected override void PublishResults(ICharSequence constraint, FilterResults results)
        {
            List<ContactModel> contactList = new List<ContactModel>();
            adapter.Clear();
            for (int i = 0; i < (results.Values.ToArray<ContactModel>()).Length; i++)
            {
                contactList.Add((results.Values.ToArray<ContactModel>())[i]);
            }
            adapter.AddAll(contactList);
            adapter.NotifyDataSetChanged();
        }
    
    }
    

    Do not forget to inherit your model class from Java.Lang.Object like:

    public class ContactModel : Java.Lang.Object
    {
        public string DisplayName { set; get; }
        public string PhotoId { set; get; }
        public long Id { set; get; }
    }
    

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    We could use linq to make a filter like:

    var newList = contactList.Where(x => x.DisplayName.Contains("filter string")).ToList();
    

    Change the condition in the lambda as you want to obtain a new list.

  • monemdcmonemdc Member ✭✭✭

    Use the following method to filter if the data is text only.
    How to use your method in a simple way to fill
    listview adapter.

    ` SearchV.QueryTextChange += textInputEdit_QueryTextChange;
    private void SearchV_QueryTextChange(object sender, SearchView.QueryTextChangeEventArgs e)
    {
    adapter.Filter.InvokeFilter(e.NewText);

        }`
    
  • LandLuLandLu Member, Xamarin Team Xamurai
    edited March 27 Accepted Answer

    Define a custom filter and consume it in your adapter like:

    Filter filter;
    public override Filter Filter 
    {
        get 
        {
            if (filter == null)
            {
                filter = new CustomFilter(this);
            }
            return filter;
        } 
    }
    
    class CustomFilter : Filter
    {
        MyAdapter adapter;
        public CustomFilter(MyAdapter adapter)
        {
            this.adapter = adapter;
        }
        protected override FilterResults PerformFiltering(ICharSequence constraint)
        {
            FilterResults results = new FilterResults();
            string prefix = constraint.ToString().ToLower();
    
            if (prefix == null || prefix.Length == 0)
            {
                results.Values = FromArray(adapter.original.ToArray());
                results.Count = adapter.original.Count();
            }
            else
            {
                var values = adapter.original.Where(x => x.DisplayName.Contains(prefix)).ToArray();
                results.Values = FromArray(values);
                results.Count = values.Count();
            }
            return results;
        }
    
        protected override void PublishResults(ICharSequence constraint, FilterResults results)
        {
            List<ContactModel> contactList = new List<ContactModel>();
            adapter.Clear();
            for (int i = 0; i < (results.Values.ToArray<ContactModel>()).Length; i++)
            {
                contactList.Add((results.Values.ToArray<ContactModel>())[i]);
            }
            adapter.AddAll(contactList);
            adapter.NotifyDataSetChanged();
        }
    
    }
    

    Do not forget to inherit your model class from Java.Lang.Object like:

    public class ContactModel : Java.Lang.Object
    {
        public string DisplayName { set; get; }
        public string PhotoId { set; get; }
        public long Id { set; get; }
    }
    
Sign In or Register to comment.