Xamarin.Android
RecyclerView
Buscar..
Conceptos básicos de RecyclerView
Este es un ejemplo del uso de Android Support Library V7 RecyclerView
. Las bibliotecas de soporte generalmente se recomiendan porque proporcionan versiones de nuevas características compatibles con versiones anteriores, proporcionan elementos útiles de IU que no están incluidos en el marco y proporcionan una gama de utilidades en las que pueden basarse las aplicaciones.
Para obtener el RecyclerView
, instalaremos los paquetes necesarios de Nuget. En primer lugar, vamos a buscar v7 recyclerview
. Desplácese hacia abajo hasta que veamos Xamarin Android Support Library - v7 RecyclerView
. Selecciónelo y haga clic en Agregar paquete .
Alternativamente, Android Support Library V7 RecyclerView
está disponible como un componente de Xamarin. Para agregar el componente, haga clic con el botón derecho en Components
dentro del proyecto de Android en el Explorador de soluciones y haga clic en Get More Components
.
Dentro de la ventana del Almacén de componentes que aparece, busque RecyclerView. En la lista de búsqueda, seleccione Android Support Library V7 RecyclerView
. Luego haga clic en Add to App
. El componente se agrega al proyecto.
El siguiente paso es agregar RecyclerView a una página. Dentro del axml
(diseño), podemos agregar RecyclerView
como se muestra a continuación.
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RecyclerView requiere que se configuren al menos dos clases auxiliares para la implementación estándar básica, a saber: Adapter
y ViewHolder
. Adapter
infla los diseños de elementos y vincula los datos a las vistas que se muestran dentro de RecyclerView. ViewHolder busca y almacena referencias de vista. El titular de la vista también ayuda a detectar clics de vista de elemento.
Aquí hay un ejemplo básico de clase de adaptador
public class MyAdapter : RecyclerView.Adapter
{
string [] items;
public MyAdapter (string [] data)
{
items = data;
}
// Create new views (invoked by the layout manager)
public override RecyclerView.ViewHolder OnCreateViewHolder (ViewGroup parent, int viewType)
{
// set the view's size, margins, paddings and layout parameters
var tv = new TextView (parent.Context);
tv.SetWidth (200);
tv.Text = "";
var vh = new MyViewHolder (tv);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
public override void OnBindViewHolder (RecyclerView.ViewHolder viewHolder, int position)
{
var item = items [position];
// Replace the contents of the view with that element
var holder = viewHolder as MyViewHolder;
holder.TextView.Text = items[position];
}
public override int ItemCount {
get {
return items.Length;
}
}
}
En el método OnCreateViewHolder
primero inflamos una Vista y creamos una instancia de la clase ViewHolder. Esta instancia tiene que ser devuelta. Este método es invocado por el adaptador cuando requiere una nueva instancia de ViewHolder. Este método no será invocado para cada celda individual. Una vez que RecyclerView tenga suficientes celdas para llenar la Vista, reutilizará las celdas antiguas que se desplazan fuera de la Vista para obtener más celdas.
El OnBindViewHolder
invoca la devolución de llamada de OnBindViewHolder
para mostrar los datos en la posición especificada. Este método debe actualizar el contenido del itemView para reflejar el item en la posición dada.
Como la celda solo contiene un solo TextView
, podemos tener un ViewHolder simple como se muestra a continuación.
public class MyViewHolder : RecyclerView.ViewHolder
{
public TextView TextView { get; set; }
public MyViewHolder (TextView v) : base (v)
{
TextView = v;
}
}
El siguiente paso es conectar las cosas en la Activity
.
RecyclerView mRecyclerView;
MyAdapter mAdapter;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);
mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);
// Plug in the linear layout manager:
var layoutManager = new LinearLayoutManager (this) { Orientation = LinearLayoutManager.Vertical };
mRecyclerView.SetLayoutManager (layoutManager);
mRecyclerView.HasFixedSize = true;
var recyclerViewData = GetData();
// Plug in my adapter:
mAdapter = new MyAdapter (recyclerViewData);
mRecyclerView.SetAdapter (mAdapter);
}
string[] GetData()
{
string[] data;
.
.
.
return data;
}
La clase LayoutManager es responsable de medir y posicionar las vistas de elementos dentro de RecyclerView, así como de determinar la política de cuándo reciclar las vistas de elementos que ya no son visibles para el usuario. Antes de RecyclerView
, tuvimos que usar ListView
para organizar las celdas como en una lista de desplazamiento vertical y GridView
para mostrar los elementos en una cuadrícula desplazable de dos dimensiones. Pero ahora podemos lograr ambos con RecyclerView configurando un LayoutManger diferente. LinearLayoutManager
organiza las celdas como en un ListView y GridLayoutManager
organiza las celdas en forma de cuadrícula.
RecyclerView con eventos Click
Este ejemplo muestra cómo configurar Click EventHandlers en un Xamarin.Android RecyclerView.
En Android Java , la forma de configurar un oyente para un clic es utilizar un onClickListener para la vista en la que se hará clic, como este:
ImageView picture = findViewById(R.id.item_picture);
picture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
Sin embargo, en Xamarin.Android, la forma de configurar un oyente para un evento Click es mediante la adición de un EventHandler, de las siguientes maneras:
1.
ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += delegate {
// do stuff
};
2.
ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += async delegate {
// await DoAsyncMethod();
// do async stuff
};
3.
ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += Picture_Click;
... // rest of your method
private void Picture_Click(object sender, EventArgs e)
{
// do stuff
}
Tenga en cuenta que el EventHandler se agrega, no se establece. Si el Click EventHandler se agrega dentro de un método GetView desde un adaptador GridView / ListView, o un método OnBindViewHolder desde un RecyclerView.Adapter, cada vez que se crea la vista del elemento, se agregará un nuevo EventHandler. Después de desplazarse varias veces, se agregarán varios EventHandlers y, cuando se haga clic en la vista, se dispararán todos.
Para evitar este problema, los EventHandlers deben darse de baja y suscribirse posteriormente en los métodos GetView o OnBindViewHolder. Además, deben usar el número 3. para configurar EventHandler, de lo contrario no será posible cancelar la suscripción de EventHandlers.
A continuación se muestra un ejemplo de un RecyclerView.Adapter con eventos Click:
public class ViewHolderPerson : Android.Support.V7.Widget.RecyclerView.ViewHolder
{
public View Item { get; private set; }
public ImageView Picture { get; private set; }
public TextView Name { get; private set; }
public ViewHolderPerson(View itemView) : base(itemView)
{
this.Item = itemView;
this.Picture = itemView.FindViewById<ImageView>(Resource.Id.Item_Person_Picture);
this.Name = itemView.FindViewById<TextView>(Resource.Id.Item_Person_Name);
}
}
public class AdapterPersons : Android.Support.V7.Widget.RecyclerView.Adapter
{
private Context context;
private Android.Support.V7.Widget.RecyclerView recyclerView;
private List<Person> persons;
public AdapterPersons(Context context, Android.Support.V7.Widget.RecyclerView recyclerView, List<Person> persons)
{
this.context = context;
this.recyclerView = recyclerView;
this.persons = persons;
}
public override int ItemCount => persons.Count;
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
Person person = this.persons[position];
((ViewHolderPerson)holder).Name.Text = person.Name;
((ViewHolderPerson)holder).Picture.SetImageBitmap(person.Picture);
// Unsubscribe and subscribe the method, to avoid setting multiple times.
((ViewHolderPerson)holder).Item.Click -= Person_Click;
((ViewHolderPerson)holder).Item.Click += Person_Click;
}
private void Person_Click(object sender, EventArgs e)
{
int position = this.recyclerView.GetChildAdapterPosition((View)sender);
Person personClicked = this.persons[position];
if(personClicked.Gender == Gender.Female)
{
Toast.MakeText(this.context, "The person clicked is a female!", ToastLength.Long).Show();
}
else if(personClicked.Gender == Gender.Male)
{
Toast.MakeText(this.context, "The person clicked is a male!", ToastLength.Long).Show();
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.item_person, parent, false);
return new ViewHolderPerson(itemView);
}
}