搜索 RecyclerView - Xamarin.Droid [英] Searching Through RecyclerView - Xamarin.Droid

查看:24
本文介绍了搜索 RecyclerView - Xamarin.Droid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找通过 recyclerView 进行搜索的 Xamarin 方式.任何人都可以请我参考有关如何以 Xamarin 方式执行此操作的演示吗?

I have been searching for the Xamarin way of searching through a recyclerView. Can anyone kindly refer me to a demo on how to do that in the Xamarin way?

推荐答案

我写了一个关于如何实现这个功能的简单演示,效果类似于 这个.您可以在此 GitHub 存储库中看到它.

I wrote up a simple demo about how to implement this feature, effect like this. You can see it in this GitHub Repository.

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

For more information, you could read the document : Filtering ListView with SearchView in Xamarin.Android and Xaver Kapeller's answer about filter a RecyclerView with a SearchView.

感谢 Xaver Kapeller 的回答,他关于 Searching Through RecyclerView 的回答很棒,所以我决定将其翻译成 Xamarin 以帮助更多人.

Thanks for Xaver Kapeller's answer, his answer about Searching Through RecyclerView was great, so I decide translate it to Xamarin to help more people.

  1. 设置SearchView

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

In the folder res/menu create a new file called main.xml. In it add an item and set the actionViewClass to android.support.v7.widget.SearchView. Since you are using the support library you have to use the namespace of the support library to set the actionViewClass attribute. Your xml file should look something like this:

 <?xml version="1.0" encoding="utf-8"?>
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
     <item android:id="@+id/action_search"
           android:title="Search"
           android:icon="@android:drawable/ic_menu_search"
           app:showAsAction="always|collapseActionView"
           app:actionViewClass="android.support.v7.widget.SearchView" />
  </menu>

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

In your Activity you have to inflate this menu xml like usual, then you can look for the MenuItem which contains the SearchView and add a delegate on QueryTextChange which we are going to use to listen for changes to the text entered into the 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<Android.Support.V7.Widget.SearchView>();

        _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

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

First, add a model class that will be used for this sample :

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

    public int DrawableId { get; set; }
}

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

It's just your basic model which will display a text in the RecyclerView. This is the layout that display the layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:padding="5dp">
    <ImageView
        android:id="@+id/chemImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_margin="5dp" />
    <TextView
        android:id="@+id/chemName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/chemImage"
        android:layout_centerInParent="true"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp" />
 </RelativeLayout>

这是 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<ImageView>(Resource.Id.chemImage);
            Caption = itemView.FindViewById<TextView>(Resource.Id.chemName);
        }
    }

3.实现RecyclerView.Adapter

3. Implementing the RecyclerView.Adapter

public class RecyclerViewAdapter : RecyclerView.Adapter, IFilterable
{
    private List<Chemical> _originalData;
    private List<Chemical> _items;
    private readonly Activity _context;

    public Filter Filter { get; private set; }

    public RecyclerViewAdapter(Activity activity, IEnumerable<Chemical> 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. 实现过滤器逻辑

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<Chemical>();
        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<Java.Lang.Object>()
                .Select(r => r.ToNetObject<Chemical>()).ToList();

        _adapter.NotifyDataSetChanged();

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

  • 用它来实现这个功能

        SetContentView(Resource.Layout.Main);
        SupportActionBar.SetDisplayShowHomeEnabled(true);
    
        var chemicals = new List<Chemical>
        {
            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<RecyclerView>(Resource.Id.recyclerView);
        _adapter = new RecyclerViewAdapter(this,chemicals);
        _LayoutManager = new LinearLayoutManager(this);
        _recyclerView.SetLayoutManager(_LayoutManager);
        _recyclerView.SetAdapter(_adapter);//
    

  • 这篇关于搜索 RecyclerView - Xamarin.Droid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆