通过RecyclerView搜索 – Xamarin.Droid

我一直在寻找Xamarin通过recyclerView搜索的方式。 有谁可以请我参加一个关于如何以Xamarin方式做到这一点的演示?

我写了一个关于如何实现这个function的简单演示,效果如下。 你可以在这个GitHub存储库中看到它。

有关更多信息,您可以阅读文档: 使用 Xamarin.Android中的 SearchView过滤ListView和Xaver Kapeller关于使用SearchView过滤RecyclerView 的答案 。

感谢Xaver Kapeller的回答,他关于通过RecyclerView搜索的答案很棒,所以我决定将其翻译成Xamarin以帮助更多人。

  1. 设置SearchView

res/menu文件夹中,创建一个名为main.xml的新文件。 在其中添加一个项目并将actionViewClass设置为android.support.v7.widget.SearchView 。 由于您使用的是支持库,因此必须使用支持库的命名空间来设置actionViewClass属性。 您的xml文件应如下所示:

      

在你的Activity你必须像往常一样膨胀这个菜单xml,然后你可以查找包含SearchViewMenuItem ,并在QueryTextChange上添加一个委托,我们将用它来监听输入到SearchView的文本的更改:

 public override bool OnCreateOptionsMenu(IMenu menu) { MenuInflater.Inflate(Resource.Menu.main, menu); var item = menu.FindItem(Resource.Id.action_search); var searchView = MenuItemCompat.GetActionView(item); _searchView = searchView.JavaCast(); _searchView.QueryTextChange += (s, e) => _adapter.Filter.InvokeFilter(e.NewText); _searchView.QueryTextSubmit += (s, e) => { // Handle enter/search button on keyboard here Toast.MakeText(this, "Searched for: " + e.Query, ToastLength.Short).Show(); e.Handled = true; }; MenuItemCompat.SetOnActionExpandListener(item, new SearchViewExpandListener(_adapter)); return true; } private class SearchViewExpandListener : Java.Lang.Object, MenuItemCompat.IOnActionExpandListener { private readonly IFilterable _adapter; public SearchViewExpandListener(IFilterable adapter) { _adapter = adapter; } public bool OnMenuItemActionCollapse(IMenuItem item) { _adapter.Filter.InvokeFilter(""); return true; } public bool OnMenuItemActionExpand(IMenuItem item) { return true; } } 
  1. 设置Adapter

首先,添加将用于此示例的模型类:

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

它只是您的基本模型,它将在RecyclerView显示文本。 这是显示布局的布局:

      

这是ChemicalHolder类的ViewHolder

  public class ChemicalHolder : RecyclerView.ViewHolder { public ImageView Image { get; private set; } public TextView Caption { get; private set; } public ChemicalHolder(View itemView) : base(itemView) { Image = itemView.FindViewById(Resource.Id.chemImage); Caption = itemView.FindViewById(Resource.Id.chemName); } } 

3. 实施RecyclerView.Adapter

 public class RecyclerViewAdapter : RecyclerView.Adapter, IFilterable { private List _originalData; private List _items; private readonly Activity _context; public Filter Filter { get; private set; } public RecyclerViewAdapter(Activity activity, IEnumerable chemicals) { _items = chemicals.OrderBy(s => s.Name).ToList(); _context = activity; Filter = new ChemicalFilter(this); } public override long GetItemId(int position) { return position; } public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.Chemical, parent, false); ChemicalHolder vh = new ChemicalHolder(itemView); return vh; } public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) { ChemicalHolder vh = holder as ChemicalHolder; var chemical = _items[position]; vh.Image.SetImageResource(chemical.DrawableId); vh.Caption.Text = chemical.Name; } public override int ItemCount { get { return _items.Count; } } public class ChemicalHolder{... private class ChemicalFilter{//Implement the Filter logic } 
  1. 实现filter逻辑

     private class ChemicalFilter : Filter { private readonly RecyclerViewAdapter _adapter; public ChemicalFilter(RecyclerViewAdapter adapter) { _adapter = adapter; } protected override FilterResults PerformFiltering(ICharSequence constraint) { var returnObj = new FilterResults(); var results = new List(); if (_adapter._originalData == null) _adapter._originalData = _adapter._items; if (constraint == null) return returnObj; if (_adapter._originalData != null && _adapter._originalData.Any()) { // Compare constraint to all names lowercased. // It they are contained they are added to results. results.AddRange( _adapter._originalData.Where( chemical => chemical.Name.ToLower().Contains(constraint.ToString()))); } // Nasty piece of .NET to Java wrapping, be careful with this! 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() .Select(r => r.ToNetObject()).ToList(); _adapter.NotifyDataSetChanged(); // Don't do this and see GREF counts rising constraint.Dispose(); results.Dispose(); } } 
  2. 使用它来实现此function

      SetContentView(Resource.Layout.Main); SupportActionBar.SetDisplayShowHomeEnabled(true); var chemicals = new List { new Chemical {Name = "Niacin", DrawableId = Resource.Drawable.Icon}, new Chemical {Name = "Biotin", DrawableId = Resource.Drawable.Icon}, new Chemical {Name = "Chromichlorid", DrawableId = Resource.Drawable.Icon}, new Chemical {Name = "Natriumselenit", DrawableId = Resource.Drawable.Icon}, 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}, }; _recyclerView = FindViewById(Resource.Id.recyclerView); _adapter = new RecyclerViewAdapter(this,chemicals); _LayoutManager = new LinearLayoutManager(this); _recyclerView.SetLayoutManager(_LayoutManager); _recyclerView.SetAdapter(_adapter);//