【问题标题】:Filterable adapter with custom object具有自定义对象的可过滤适配器
【发布时间】:2017-11-02 09:00:26
【问题描述】:

我想在 xamarin.android 的列表视图(自定义对象)中添加自动完成文本框。

我有一个从字符串数组填充的列表视图。我想使用自定义对象填充我的列表视图。

以下代码有效,但适用于字符串数组。为自定义对象实现我的适配器的任何帮助都会有所帮助。

代码如下:

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <EditText
        android:id="@+id/search"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:hint="Enter search query" />
    <Button
        android:id="@+id/dosearch"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Filter list" />
    <ListView
        android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

MainActivity

public class MainActivity : Activity
    {
        Button _button;
        ListView _listview;
        EditText _filterText;
        FilterableAdapter _adapter;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            _button = FindViewById<Button> (Resource.Id.dosearch);
            _listview = FindViewById<ListView> (Resource.Id.list);
            _filterText = FindViewById<EditText> (Resource.Id.search);
            _adapter = new FilterableAdapter (this, Android.Resource.Layout.SimpleListItem1, GetItems());
            _listview.Adapter = _adapter;

            _button.Click += delegate {
                // filter the adapter here
                _adapter.Filter.InvokeFilter(_filterText.Text);
            };

            _filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
                // filter on text changed
                var searchTerm = _filterText.Text;
                if (String.IsNullOrEmpty(searchTerm)) {
                    _adapter.ResetSearch();
                } else {
                    _adapter.Filter.InvokeFilter(searchTerm);
                }
            };
        }

        string[] GetItems ()
        {
           string[] names = new string[] { "abc", "xyz", "yyy", "aaa" };
           return names;
        }
    }

    public class FilterableAdapter : ArrayAdapter, IFilterable
    {
        LayoutInflater inflater;
        Filter filter;
        Activity context;
        public string[] AllItems;
        public string[] MatchItems;

        public FilterableAdapter (Activity context, int txtViewResourceId, string[] items) : base(context, txtViewResourceId, items)
        {
            inflater = context.LayoutInflater;
            filter = new SuggestionsFilter(this);
            AllItems = items;
            MatchItems = items;
        }

        public override int Count {
            get {
                return MatchItems.Length;
            }
        }

        public override Java.Lang.Object GetItem (int position)
        {
            return MatchItems[position];
        }

        public override View GetView (int position, View convertView, ViewGroup parent)
        {
            View view = convertView;
            if (view == null)
                view = inflater.Inflate(Android.Resource.Layout.SimpleDropDownItem1Line, null);

            view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = MatchItems[position];

            return view;
        }

        public override Filter Filter {
            get {
                return filter;
            }
        }

        public void ResetSearch() {
            MatchItems = AllItems;
            NotifyDataSetChanged ();
        }

        class SuggestionsFilter : Filter
        {
            readonly FilterableAdapter _adapter;

            public SuggestionsFilter (FilterableAdapter adapter) : base() {
                _adapter = adapter;
            }

            protected override Filter.FilterResults PerformFiltering (Java.Lang.ICharSequence constraint)
            {
                FilterResults results = new FilterResults();
                if (!String.IsNullOrEmpty (constraint.ToString ())) {
                    var searchFor = constraint.ToString ();
                    Console.WriteLine ("searchFor:" + searchFor);
                    var matchList = new List<string> ();

                    var matches = 
                        from i in _adapter.AllItems
                        where i.IndexOf (searchFor, StringComparison.InvariantCultureIgnoreCase) >= 0
                        select i;

                    foreach (var match in matches) {
                        matchList.Add (match);
                    }

                    _adapter.MatchItems = matchList.ToArray ();
                    Console.WriteLine ("resultCount:" + matchList.Count);

                    Java.Lang.Object[] matchObjects;
                    matchObjects = new Java.Lang.Object[matchList.Count];
                    for (int i = 0; i < matchList.Count; i++) {
                        matchObjects [i] = new Java.Lang.String (matchList [i]);
                    }

                    results.Values = matchObjects;
                    results.Count = matchList.Count;
                } else {
                    _adapter.ResetSearch ();
                }
                return results;
            }

            protected override void PublishResults (Java.Lang.ICharSequence constraint, Filter.FilterResults results)
            {
                _adapter.NotifyDataSetChanged();
            }
        }
    }

我想要这样的 getItem 方法:

 public List<ListObject> GetItems()
 {
     List<ListObject> model = new List<ListObject>();
     model.Add(new ListObject { id = 1, Name = "abc" });
     model.Add(new ListObject { id = 1, Name = "bcd" });
     model.Add(new ListObject { id = 1, Name = "def" });
     model.Add(new ListObject { id = 1, Name = "fgh" });
     return model;
 }

这样做的主要原因是我希望根据在 edittext 中键入的数据过滤我的列表。然后取选中的Id,做剩下的计算。

【问题讨论】:

    标签: c# xamarin.android android-arrayadapter


    【解决方案1】:

    带有自定义对象的可过滤适配器

    我写了一个demo 关于如何搜索RecyclerView,在我的演示中我用List&lt;Chemical&gt; 填充我的RecyclerView。更多详细信息,您可以阅读我的回答:Searching Through RecyclerView

    我的Chemical 班级:

    public class Chemical
    {
        public string Name { get; set; }
        public int DrawableId { get; set; }
    }
    

    当填充 RecyclerView 时:

    var chemicals = new List<Chemical>
    {
        new Chemical {Name = "Manganosulfate", DrawableId = Resource.Drawable.Icon},
        new Chemical {Name = "Natriummolybdate", DrawableId = Resource.Drawable.Icon},
        new Chemical {Name = "Ergocalciferol", DrawableId = Resource.Drawable.Icon},
        new Chemical {Name = "Cyanocobalamin", DrawableId = Resource.Drawable.Icon},
    };
    
    _adapter = new RecyclerViewAdapter(this,chemicals);
    

    编辑:

    由于你使用ListView,你可以参考Cheesebaron's SearchView-Sample,我想这就是你想要的。

    不要忘记在您的项目中添加ObjectExtensions 类。

    【讨论】:

      【解决方案2】:

      我找到了想要的结果。我改变了我的适配器,这对我有用:

          public class FilterableAdapter : ArrayAdapter, IFilterable
          {
              LayoutInflater inflater;
              Filter filter;
              Activity context;
              public List<ListObject> AllItems;
              public List<ListObject> MatchItems;
      
              public FilterableAdapter(Activity context, int txtViewResourceId, List<ListObject> items) : base(context, txtViewResourceId, items)
              {
                  inflater = context.LayoutInflater;
                  filter = new SuggestionsFilter(this);
                  AllItems = items;
                  MatchItems = items;
              }
      
              public override int Count
              {
                  get
                  {
                      return MatchItems.Count;
                  }
              }
      
              public override Java.Lang.Object GetItem(int position)
              {
                  return null;
              }
      
              public ListObject GetMatchedItem(int position)
              {
                  return MatchItems[position];
              }
      
      
              public override View GetView(int position, View convertView, ViewGroup parent)
              {
                  View view = convertView;
                  if (view == null)
                      view = inflater.Inflate(Resource.Layout.custom_listView, null);
      
                  view.FindViewById<TextView>(Resource.Id.list_content).Text = MatchItems[position].PICPropertyName;
      
                  return view;
              }
      
              public override Filter Filter
              {
                  get
                  {
                      return filter;
                  }
              }
      
              public void ResetSearch()
              {
                  MatchItems = AllItems;
                  NotifyDataSetChanged();
              }
      
              class SuggestionsFilter : Filter
              {
                  readonly FilterableAdapter _adapter;
      
                  public SuggestionsFilter(FilterableAdapter adapter) : base()
                  {
                      _adapter = adapter;
                  }
      
                  protected override Filter.FilterResults PerformFiltering(Java.Lang.ICharSequence constraint)
                  {
                      FilterResults results = new FilterResults();
                      if (!String.IsNullOrEmpty(constraint.ToString()))
                      {
                          var searchFor = constraint.ToString();
                          Console.WriteLine("searchFor:" + searchFor);
                          var matchList = new List<ListObject>();
                          var matches = _adapter.AllItems.Where(i => i.name.Contains(searchFor));
                          foreach (var match in matches)
                          {
                              matchList.Add(match);
                          }
      
                          _adapter.MatchItems = matchList;
                          Console.WriteLine("resultCount:" + matchList.Count);
      
                          List<ListObject> matchObjects = new List<ListObject>();
                          for (int i = 0; i < matchList.Count; i++)
                          {
                              matchObjects.Add(matchList[i]);
                          }
      
                          results.Count = matchList.Count;
                      }
                      else
                      {
                          _adapter.ResetSearch();
                      }
                      return results;
                  }
      
                  protected override void PublishResults(Java.Lang.ICharSequence constraint, Filter.FilterResults results)
                  {
                      _adapter.NotifyDataSetChanged();
                  }
              }
          }
      
          public class ListObject {
              public int id { get; set; }
              public int name { get; set; }
          }
      

      【讨论】:

        猜你喜欢
        • 2011-08-12
        • 2012-06-29
        • 1970-01-01
        • 1970-01-01
        • 2014-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多