Xamarin.Android
RecyclerView
Recherche…
RecyclerView Basics
Ceci est un exemple d'utilisation de la Android Support Library V7 RecyclerView
. Les bibliothèques de support sont généralement recommandées car elles fournissent des versions rétrocompatibles des nouvelles fonctionnalités, fournissent des éléments d'interface utilisateur utiles qui ne sont pas inclus dans la structure et fournissent une gamme d'utilitaires pouvant être utilisés par les applications.
Pour obtenir le RecyclerView
, nous allons installer les paquets Nuget nécessaires. Tout d'abord, nous rechercherons v7 recyclerview
. Faites défiler la liste jusqu'à ce que nous Xamarin Android Support Library - v7 RecyclerView
. Sélectionnez-le et cliquez sur Ajouter un package .
Sinon, Android Support Library V7 RecyclerView
est disponible en tant que composant Xamarin. Pour ajouter le composant, cliquez avec le bouton droit sur Components
du projet Android dans l'explorateur de solutions et cliquez sur Get More Components
.
Dans la fenêtre Component Store qui apparaît, recherchez RecyclerView. Dans la liste de recherche, sélectionnez Android Support Library V7 RecyclerView
. Cliquez ensuite sur Add to App
. Le composant est ajouté au projet.
La prochaine étape consiste à ajouter RecyclerView à une page. Dans le axml
(layout), nous pouvons ajouter RecyclerView
comme ci-dessous.
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RecyclerView nécessite la configuration d'au moins deux classes d'assistance pour l'implémentation standard de base, à savoir: Adapter
et ViewHolder
. Adapter
gonfle les dispositions d'éléments et lie les données aux vues affichées dans RecyclerView. ViewHolder recherche et stocke les références de vue. Le porte-vues permet également de détecter les clics sur les vues d'objets.
Voici un exemple de base de la classe d'adaptateur
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;
}
}
}
Dans la méthode OnCreateViewHolder
, nous OnCreateViewHolder
abord une vue et créons une instance de la classe ViewHolder. Cette instance doit être renvoyée. Cette méthode est appelée par l'adaptateur lorsqu'il nécessite une nouvelle instance de ViewHolder. Cette méthode ne sera pas invoquée pour chaque cellule. Une fois que RecyclerView a suffisamment de cellules pour remplir la vue, il réutilisera les anciennes cellules qui défilent hors de la vue pour d'autres cellules.
Le rappel OnBindViewHolder
est OnBindViewHolder
par l'adaptateur pour afficher les données à la position spécifiée. Cette méthode doit mettre à jour le contenu de itemView pour refléter l'élément à la position donnée.
Comme la cellule ne contient qu'un seul TextView
, nous pouvons avoir un ViewHolder simple comme ci-dessous.
public class MyViewHolder : RecyclerView.ViewHolder
{
public TextView TextView { get; set; }
public MyViewHolder (TextView v) : base (v)
{
TextView = v;
}
}
La prochaine étape consiste à connecter des objets dans 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 classe LayoutManager est chargée de mesurer et de positionner les vues d'éléments dans RecyclerView et de déterminer la stratégie de recyclage des vues d'éléments qui ne sont plus visibles pour l'utilisateur. Avant RecyclerView
, nous devions utiliser ListView
pour organiser les cellules comme dans une liste déroulante verticale et GridView
pour afficher les éléments dans une grille à deux dimensions et défilant. Mais maintenant, nous pouvons réaliser les deux avec RecyclerView en définissant un LayoutManger différent. LinearLayoutManager
organise les cellules comme dans ListView et GridLayoutManager
organise les cellules en mode Grid.
RecyclerView avec les événements Click
Cet exemple montre comment définir Click EventHandlers dans un Xamarin.Android RecyclerView.
Dans Android Java , la façon de configurer un écouteur pour un clic consiste à utiliser un onClickListener pour la vue sur laquelle l'utilisateur cliquera, comme ceci:
ImageView picture = findViewById(R.id.item_picture);
picture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
Toutefois, dans Xamarin.Android, la manière de configurer un écouteur pour un événement Click consiste à ajouter un gestionnaire d'événements, de l'une des manières suivantes:
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
}
Notez que le gestionnaire d'événements est ajouté, pas défini. Si le gestionnaire d'événements Click Click est ajouté à l'intérieur d'une méthode GetView à partir d'un adaptateur GridView / ListView ou d'une méthode OnBindViewHolder à partir de RecyclerView.Adapter, un nouveau EventHandler sera ajouté chaque fois que la vue d'élément est créée. Après avoir fait défiler plusieurs fois, plusieurs EventHandlers seront ajoutés et lorsque la vue sera cliquée, ils seront tous déclenchés.
Pour éviter ce problème, les EventHandlers doivent être désabonnés et abonnés ultérieurement dans les méthodes GetView ou OnBindViewHolder. De plus, ils doivent utiliser le numéro 3. pour définir le gestionnaire d'événements, sinon il ne sera pas possible de se désinscrire des gestionnaires d'événements.
Un exemple de RecyclerView.Adapter avec des événements Click est illustré ci-dessous:
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);
}
}