Xamarin.Android
RecyclerView
Suche…
RecyclerView-Grundlagen
Dies ist ein Beispiel für die Verwendung der Android Support Library V7 RecyclerView
. Unterstützungsbibliotheken werden im Allgemeinen empfohlen, da sie abwärtskompatible Versionen neuer Funktionen bereitstellen, nützliche Elemente der Benutzeroberfläche enthalten, die nicht im Framework enthalten sind, und eine Reihe von Dienstprogrammen bereitstellen, auf die Apps zurückgreifen können.
Um RecyclerView
, installieren wir die erforderlichen Nuget-Pakete. Zuerst suchen wir nach v7 recyclerview
. Scrollen Sie nach unten, bis die Xamarin Android Support Library - v7 RecyclerView
. Wählen Sie es aus und klicken Sie auf Paket hinzufügen .
Alternativ ist die Android Support Library V7 RecyclerView
als Xamarin-Komponente verfügbar. Um die Komponente hinzuzufügen, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Components
im Android-Projekt, und klicken Sie auf Get More Components
.
Suchen Sie im angezeigten Fenster "Component Store" nach RecyclerView. Android Support Library V7 RecyclerView
in der Suchliste Android Support Library V7 RecyclerView
. Klicken Sie dann auf Add to App
. Die Komponente wird dem Projekt hinzugefügt.
Der nächste Schritt ist das Hinzufügen der RecyclerView zu einer Seite. In der axml
Datei (Layoutdatei) können Sie wie axml
RecyclerView
hinzufügen.
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Für RecyclerView müssen mindestens zwei ViewHolder
für die grundlegende Standardimplementierung eingerichtet werden: Adapter
und ViewHolder
. Adapter
bläst Elementlayouts auf und bindet Daten an Ansichten, die in einer RecyclerView angezeigt werden. ViewHolder sucht und speichert Ansichtsreferenzen. Der Ansichtshalter hilft auch beim Erkennen von Elementklicks.
Hier ist ein grundlegendes Beispiel für die Adapterklasse
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;
}
}
}
In der OnCreateViewHolder
Methode OnCreateViewHolder
wir zuerst eine View auf und erstellen eine Instanz der ViewHolder-Klasse. Diese Instanz muss zurückgegeben werden. Diese Methode wird vom Adapter aufgerufen, wenn eine neue Instanz von ViewHolder erforderlich ist. Diese Methode wird nicht für jede einzelne Zelle aufgerufen. Wenn RecyclerView genug Zellen zum Füllen der Ansicht hat, werden die alten Zellen, die aus der Ansicht gescrollt werden, für weitere Zellen wiederverwendet.
Der OnBindViewHolder
Callback wird vom Adapter aufgerufen, um die Daten an der angegebenen Position anzuzeigen. Diese Methode sollte den Inhalt der itemView aktualisieren, um das Element an der angegebenen Position wiederzugeben.
Da die Zelle nur eine einzige TextView
, können wir einen einfachen ViewHolder wie folgt verwenden.
public class MyViewHolder : RecyclerView.ViewHolder
{
public TextView TextView { get; set; }
public MyViewHolder (TextView v) : base (v)
{
TextView = v;
}
}
Der nächste Schritt besteht darin, Dinge in 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;
}
Die LayoutManager-Klasse ist für das Messen und Positionieren von Elementansichten in einer RecyclerView sowie für die Festlegung der Richtlinie dafür verantwortlich, wann Elementansichten wieder verwendet werden sollen, die für den Benutzer nicht mehr sichtbar sind. Vor der RecyclerView
mussten wir ListView
, um Zellen in einer vertikal scrollenden Liste GridView
, und GridView
, um Elemente in einem zweidimensionalen, scrollbaren Raster anzuzeigen. Beides können wir jetzt mit RecyclerView erreichen, indem wir einen anderen LayoutManger einstellen. LinearLayoutManager
ordnet Zellen wie in einem ListView an, und GridLayoutManager
ordnet Zellen im Grid- GridLayoutManager
.
RecyclerView mit Click-Ereignissen
Dieses Beispiel zeigt, wie Sie Click EventHandlers in einer Xamarin.Android RecyclerView festlegen.
In Android Java können Sie einen Listener für einen Click einrichten, indem Sie einen onClickListener für die Ansicht verwenden, auf die Sie klicken.
ImageView picture = findViewById(R.id.item_picture);
picture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
In Xamarin.Android können Sie jedoch einen Listener für ein Click-Ereignis einrichten, indem Sie einen EventHandler auf folgende Weise hinzufügen :
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
}
Beachten Sie, dass der EventHandler hinzugefügt und nicht festgelegt wird. Wenn der Click-EventHandler aus einer GridView / ListView-Adapter oder einer OnBindViewHolder-Methode aus einem RecyclerView.Adapter in eine GetView-Methode eingefügt wird, wird jedes Mal, wenn die Elementansicht erstellt wird, ein neuer EventHandler hinzugefügt. Nach mehrmaligem Scrollen werden mehrere EventHandler hinzugefügt. Wenn Sie auf die Ansicht klicken, werden alle ausgelöst.
Um dieses Problem zu vermeiden, müssen die EventHandlers abbestellt und anschließend in den Methoden GetView oder OnBindViewHolder abonniert werden. Sie müssen außerdem die Nummer 3. verwenden , um den EventHandler festzulegen. Andernfalls können die EventHandlers nicht abbestellt werden.
Ein Beispiel eines RecyclerView.Adapter mit Click-Ereignissen wird unten gezeigt:
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);
}
}