Filter ListView with SearchView xamarin

前提是你 提交于 2020-08-10 20:03:11

问题


I want to filter Listview by Searchview

I use the following Adapter for the filter and it works if I haven't made any new additions to the adapter

When I add a new item to Listview, the search stops completely until I restart the program after adding, modifying or deleting it

full code

adapter class


回答1:


Do you want to achieve the result like following GIF?

If you want to add the item to the listview, based on your adapter, you should item in the adapter like following code.

   public class TableItemAdapter : BaseAdapter<TableItem>, IFilterable
    {
        public List<TableItem> _originalData;
        public List<TableItem> _items;
        private readonly Activity _context;


        public TableItemAdapter(Activity activity, IEnumerable<TableItem> tableitems)
        {

            _items = tableitems.ToList();
            _context = activity;

            Filter = new TableItemFilter(this);
        }

        //Add data to the `_items`, listview will be updated, if add data in the activity, 
        //there are two different lists, so listview will not update.
        public void AddData(TableItem tableItem)
        {
            _items.Add(tableItem);
            NotifyDataSetChanged();
        }

        public override TableItem this[int position]
        {
            get { return _items[position]; }
        }

        public Filter Filter { get; private set; }

        public override int Count
        {
            get { return _items.Count; }
        }

        public override long GetItemId(int position)
        {
            return position;
        }



        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            var item = _items[position];

            View view = convertView;


            if (view == null) // no view to re-use, create new
                view = convertView ?? _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
            //view = _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
            view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
            view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;


            return view;

        }
        public override void NotifyDataSetChanged()
        {
           // this.NotifyDataSetChanged();
          base.NotifyDataSetChanged();
        }
    }

    public class TableItemFilter :Filter
    {
        private readonly TableItemAdapter _adapter;
        public TableItemFilter(TableItemAdapter adapter)
        {
            _adapter = adapter;
        }

        protected override FilterResults PerformFiltering(ICharSequence constraint)
        {
            var returnObj = new FilterResults();
            var results = new List<TableItem>();


            if (_adapter._originalData == null)
                _adapter._originalData = _adapter._items;

            if (constraint == null) return returnObj;

            if (_adapter._originalData != null && _adapter._originalData.Any())
            {

                results.AddRange(
                    _adapter._originalData.Where(
                        item => item.SubHeading.ToLower().Contains(constraint.ToString()) | item.Heading.ToLower().Contains(constraint.ToString())));

            }


            returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray());
            returnObj.Count = results.Count;

            constraint.Dispose();

            return returnObj;
        }



        protected override void PublishResults(ICharSequence constraint, FilterResults results)
        {
            using (var values = results.Values)
                _adapter._items = values.ToArray<Java.Lang.Object>().Select(r => r.ToNetObject<TableItem>()).ToList();

            _adapter.NotifyDataSetChanged();

            // Don't do this and see GREF counts rising
            constraint.Dispose();
            results.Dispose();
        }

    }

    public  class JavaHolder : Java.Lang.Object
    {
        public readonly object Instance;

        public JavaHolder(object instance)
        {
            Instance = instance;
        }


    }

    public static class ObjectExtensions
    {
        public static TObject ToNetObject<TObject>(this Java.Lang.Object value)
        {
            if (value == null)
                return default(TObject);

            if (!(value is JavaHolder))
                throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted.");

            TObject returnVal;
            try { returnVal = (TObject)((JavaHolder)value).Instance; }
            finally { value.Dispose(); }
            return returnVal;
        }

        public static Java.Lang.Object ToJavaObject<TObject>(this TObject value)
        {
            if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType)
                return null;

            var holder = new JavaHolder(value);

            return holder;
        }
    }
}

Then in the activity, you add the data by adapter.

 private void Button1_Click(object sender, System.EventArgs e)
        {

            tableItemAdapter.AddData(new TableItem() { Heading = "test1222", SubHeading = "sub Test" });


        }

Here is my demo, you can download it. https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/XAListViewSearchDemo.zip



来源:https://stackoverflow.com/questions/61723948/filter-listview-with-searchview-xamarin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!