Android Recyclerview tutorial: RecyclerView list with CardView as row
RecyclerView
CardView
Android adapter
RecyclerView: Introduction
As I mentioned, RecyclerView is more flexible that ListView even if it introduces some complexities. We all know how to use ListView in our app and we know if we want to increase the ListView performances we can use a pattern called ViewHolder. This pattern consists of a simple class that holds the references to the UI components for each row in the ListView. This pattern avoids looking up the UI components all the time the system shows a row in the list. Even if this pattern introduces some benefits, we can implement the ListView without using it at all. RecyclerView forces us to use the ViewHolder pattern. To show how we can use the RecyclerView, we can suppose we want to create a simple app that shows a list of contact cards. The first thing we should do is create the main layout. RecyclerView is very similar to the ListView and we can use them in the same way:<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"As you'll notice from the layout shown above, the RecyclerView is available in the Android support library, so we have to modify build.gradle to include this dependency:
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/cardList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
dependencies {Now, in the onCreate method we can get the reference to our RecyclerView and configure it:
...
compile 'com.android.support:recyclerview-v7:21.0.0'
}
@OverrideIf you look at the code above, you'll notice some differences between the RecyclerView and ListView. RecyclerView requires a layout manager. This component positions item views inside the row and determines when it is time to recycle the views. The library provides a default layout manager called LinearLayoutManager.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
RecyclerView recList = (RecyclerView) findViewById(R.id.cardList);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
}
CardViewThe CardView UI component shows information inside cards. We can customise its corners, the elevation and so on. We want to use this component to show contact information. These cards will be the rows of RecyclerView and we will see later how to integrate these two components. By now, we can define our card layout:
<android.support.v7.widget.CardViewAs you can see, the CardView is very simple to use. This component is available in another android support library so we have to add this dependency too:
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardCornerRadius="4dp"
android:layout_margin="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@color/bkg_card"
android:text="contact det"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:textSize="14dp"/>
<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/title"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>
<TextView
android:id="@+id/txtSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Surname"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/txtName"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>
<TextView
android:id="@+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textSize="10dp"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_marginRight="150dp"
android:layout_alignBaseline="@id/txtName"/>
</RelativeLayout>
dependencies {
compile 'com.android.support:cardview-v7:21.0.0'
compile 'com.android.support:recyclerview-v7:21.0.0'
}
RecyclerView: Adapter
The adapter is a component that stands between the data model we want to show in our app UI and the UI component that renders this information. In other words, an adapter guides the way the information are shown in the UI. So if we want to display our contacts, we need an adapter for the RecyclerView. This adapter must extend a class called RecyclerView.Adapter passing our class that implements the ViewHolder pattern:public class MyAdapter extends RecyclerView.Adapter<MyHolder> { ..... }We now have to override two methods so that we can implement our logic: onCreateViewHolder is called whenever a new instance of our ViewHolder class is created, and onBindViewHolder is called when the OS binds the view with the data -- or, in other words, the data is shown in the UI. In this case, the adapter helps us combine the RecyclerView and CardView. The layout we defined before for the cards will be the row layout of our contact list in the RecyclerView. Before doing it, we have to define our data model that stands at the base of our UI (i.e. what information we want to show). For this purpose, we can define a simple class:
public class ContactInfo {And finally, we are ready to create our adapter. If you remember what we said before about Viewholder pattern, we have to code our class that implements it:
protected String name;
protected String surname;
protected String email;
protected static final String NAME_PREFIX = "Name_";
protected static final String SURNAME_PREFIX = "Surname_";
protected static final String EMAIL_PREFIX = "email_";
}
public static class ContactViewHolder extends RecyclerView.ViewHolder {Look at the code, in the class constructor we get the reference to the views we defined in our card layout. Now it is time to code our adapter:
protected TextView vName;
protected TextView vSurname;
protected TextView vEmail;
protected TextView vTitle;
public ContactViewHolder(View v) {
super(v);
vName = (TextView) v.findViewById(R.id.txtName);
vSurname = (TextView) v.findViewById(R.id.txtSurname);
vEmail = (TextView) v.findViewById(R.id.txtEmail);
vTitle = (TextView) v.findViewById(R.id.title);
}
}
public class ContactAdapter extendsIn our implementation, we override onBindViewHolder where we bind the data (our contact info) to the Views. Notice that we don't look up UI components but simply use the references stored in our ContactViewHolder. In onCreateViewHolder we return our ContactViewHolderinflating the row layout (the CardView in our case). Run the app and you'll get the results shown below:
RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
private List<ContactInfo> contactList;
public ContactAdapter(List<ContactInfo> contactList) {
this.contactList = contactList;
}
@Override
public int getItemCount() {
return contactList.size();
}
@Override
public void onBindViewHolder(ContactViewHolder contactViewHolder, int i) {
ContactInfo ci = contactList.get(i);
contactViewHolder.vName.setText(ci.name);
contactViewHolder.vSurname.setText(ci.surname);
contactViewHolder.vEmail.setText(ci.email);
contactViewHolder.vTitle.setText(ci.name + " " + ci.surname);
}
@Override
public ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.card_layout, viewGroup, false);
return new ContactViewHolder(itemView);
}
public static class ContactViewHolder extends RecyclerView.ViewHolder {
...
}
}
Source code available @github
This post was originaly published on Binpress.
0 comments:
Post a Comment