c# android xamarin xamarin.android

c# - Búsqueda a través de RecyclerView-Xamarin.Droid



android xamarin.android (1)

Escribí una demostración simple sobre cómo implementar esta característica, efecto como este . Puedes verlo en este Repositorio de GitHub .

Para obtener más información, puede leer el documento: Filtrar ListView con SearchView en Xamarin. Android y la respuesta de Xaver Kapeller sobre filtrar un RecyclerView con un SearchView .

Gracias por la respuesta de Xaver Kapeller, su respuesta sobre Searching Through RecyclerView fue excelente, por lo que decido traducirla a Xamarin para ayudar a más personas.

  1. Configurando SearchView

En la carpeta res/menu crea un nuevo archivo llamado main.xml . En él, agregue un elemento y configure actionViewClass en android.support.v7.widget.SearchView . Como está utilizando la biblioteca de soporte, debe usar el espacio de nombre de la biblioteca de soporte para establecer el atributo actionViewClass . Su archivo xml debería verse más o menos así:

<?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>

En su Activity debe inflar este menú xml como de costumbre, luego puede buscar el MenuItem que contiene SearchView y agregar un delegado en QueryTextChange que vamos a usar para escuchar los cambios al texto ingresado en 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. Configurando el Adapter

Primero, agregue una clase de modelo que se usará para esta muestra:

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

Es solo su modelo básico el que mostrará un texto en RecyclerView . Este es el diseño que muestra el diseño:

<?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>

Este es el ViewHolder para la clase ChemicalHolder :

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. Implementando 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. Implementando la lógica del filtro

    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(); } }

  2. Úselo para implementar esta característica

    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);//

He estado buscando la forma Xamarin de buscar a través de un recyclerView. ¿Alguien puede referirme amablemente a una demostración sobre cómo hacer eso al estilo Xamarin?