Xamarin.Android
RecyclerView
Sök…
Grunderna i RecyclerView
Detta är ett exempel på att använda Android Support Library V7 RecyclerView
. Supportbibliotek rekommenderas vanligtvis eftersom de tillhandahåller bakåtkompatibla versioner av nya funktioner, tillhandahåller användbara användargränssnittselement som inte ingår i ramverket och ger en rad verktyg som appar kan dra på.
För att få RecyclerView
kommer vi att installera nödvändiga Nuget-paket. Först söker vi efter v7 recyclerview
. Rulla ner tills vi ser Xamarin Android Support Library - v7 RecyclerView
. Markera det och klicka på Lägg till paket .
Alternativt är Android Support Library V7 RecyclerView
tillgängligt som en Xamarin-komponent. För att lägga till komponenten högerklickar du på Components
inom Android-projektet i Solution explorer och klickar på Get More Components
.
Sök efter RecyclerView i fönstret Component Store. I söklistan väljer du Android Support Library V7 RecyclerView
. Klicka sedan på Add to App
. Komponenten läggs till i projektet.
Nästa steg är att lägga till RecyclerView på en sida. I axml
(layout) kan vi lägga till RecyclerView
enligt nedan.
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RecyclerView kräver att minst två hjälparklasser ska ställas in för grundläggande standardimplementering: Adapter
och ViewHolder
. Adapter
blåser upp objektlayouter och binder data till vyer som visas i en RecyclerView. ViewHolder tittar upp och lagrar visningsreferenser. Visningshållaren hjälper också till att upptäcka klick på artikelvy.
Här är ett grundläggande exempel på Adapter Class
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;
}
}
}
I OnCreateViewHolder
metoden OnCreateViewHolder
vi först upp en vy och skapar en instans av klassen ViewHolder. Denna instans måste returneras. Denna metod åberopas av adaptern när den kräver en ny instans av ViewHolder. Den här metoden kommer inte att påkallas för varje cell. När RecyclerView har tillräckligt med celler för att fylla vyn, kommer den att använda de gamla cellerna som rullas ut från vyn för ytterligare celler.
OnBindViewHolder
återuppringning aktiveras av Adapter för att visa data på den angivna positionen. Den här metoden bör uppdatera innehållet i artikelvyn för att återspegla objektet vid den angivna positionen.
Eftersom cellen bara innehåller en enda TextView
kan vi ha en enkel ViewHolder som nedan.
public class MyViewHolder : RecyclerView.ViewHolder
{
public TextView TextView { get; set; }
public MyViewHolder (TextView v) : base (v)
{
TextView = v;
}
}
Nästa steg är att koppla upp saker i 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;
}
LayoutManager-klassen ansvarar för att mäta och placera objektvyer i en RecyclerView samt bestämma policyn för när du ska återvinna objektvyer som inte längre är synliga för användaren. Innan RecyclerView
var vi tvungna att använda ListView
att ordna celler i som i en vertikal rullningslista och GridView
att visa objekt i ett tvådimensionellt, rullningsbart rutnät. Men nu kan vi uppnå båda med RecyclerView genom att ställa in en annan LayoutManger. LinearLayoutManager
ordnar celler som i en ListView och GridLayoutManager
ordnar celler Grid-mode.
RecyclerView med Click-händelser
Detta exempel visar hur man ställer in Click EventHandlers i en Xamarin.Android RecyclerView.
I Android Java använder man en onClickListener för den vy som kommer att klickas på så sätt:
ImageView picture = findViewById(R.id.item_picture);
picture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
Men i Xamarin.Android är sättet att ställa in en lyssnare för en Click-händelse genom att lägga till en EventHandler på följande sätt:
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
}
Observera att EventHandler läggs till, inte inställd. Om Click EventHandler läggs till i en GetView-metod från en GridView / ListView-adapter, eller en OnBindViewHolder-metod från en RecyclerView.Adapter, läggs en ny EventHandler till varje gång som objektvyn skapas. Efter att ha bläddrat flera gånger läggs flera EventHandlers till, och när vyn klickas av kommer alla att avfyras.
För att undvika detta problem måste EventHandlers avregistreras och prenumereras därefter i GetView- eller OnBindViewHolder-metoderna. De måste också använda sättet 3. sätt att ställa in EventHandler, annars kommer det inte att vara möjligt att avregistrera EventHandlers.
Ett exempel på en RecyclerView.Adapter med Click-händelser visas nedan:
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);
}
}