RecyclerView
Creación de un RecyclerView
RecyclerView (punto 4.3 de la unidad 2)
Creación de listas con RecyclerView:
El patrón ViewHolder y su uso en un RecyclerView:
Cómo usar un RecyclerView:
Uso de un ListView:
Using an ArrayAdapter with ListView
El patrón ViewHolder, qué es y cómo utilizarlo
How ListView’s recycling mechanism works
Uso de un RecyclerView:
Ejercicio: Crear un RecyclerView de contactos
Using the RecyclerView
Using a RecyclerView
has the following key steps:
- Define a model class to use as the data source
- Add a
RecyclerView
to your activity to display the items - Create a custom row layout XML file to visualize the item
- Create a
RecyclerView.Adapter
andViewHolder
to render the item - Bind the adapter to the data source to populate the
RecyclerView
Modelo: Contact.java
public class Contact { private String mName; private boolean mOnline; public Contact(String name, boolean online) { mName = name; mOnline = online; } public String getName() { return mName; } public boolean isOnline() { return mOnline; } private static int lastContactId = 0; public static ArrayList<Contact> createContactsList(int numContacts) { ArrayList<Contact> contacts = new ArrayList<Contact>(); for (int i = 1; i <= numContacts; i++) { contacts.add(new Contact("Person " + ++lastContactId, i <= numContacts / 2)); } return contacts; } }
Create the RecyclerView within Layout
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/addContact" android:layout_width="387dp" android:layout_height="61dp" android:layout_marginStart="8dp" android:layout_marginTop="76dp" android:layout_marginEnd="8dp" android:layout_marginBottom="25dp" android:text="@string/a_adir_contacto" app:layout_constraintBottom_toTopOf="@+id/rvContacts" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.736" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvContacts" android:layout_width="402dp" android:layout_height="545dp" android:layout_marginStart="5dp" android:layout_marginTop="10dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/addContact" /> </androidx.constraintlayout.widget.ConstraintLayout>
Creating the Custom Row Layout
item_contact.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp" > <TextView android:id="@+id/contact_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/message_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="16dp" android:paddingRight="16dp" android:textSize="10sp" tools:ignore="SpeakableTextPresentCheck" /> </LinearLayout>
Creating the RecyclerView Adapter
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> { // Store a member variable for the contacts private List<Contact> mContacts; // Pass in the contact array into the constructor public ContactsAdapter(List<Contact> contacts) { mContacts = contacts; } // Add the interface OnItemClickListener // Provide a direct reference to each of the views within a data item // Used to cache the views within the item layout for fast access public class ViewHolder extends RecyclerView.ViewHolder { // Your holder should contain a member variable // for any view that will be set as you render a row public TextView nameTextView; public Button messageButton; // We also create a constructor that accepts the entire item row // and does the view lookups to find each subview public ViewHolder(View itemView) { // Stores the itemView in a public final member variable that can be used // to access the context from any ViewHolder instance. super(itemView); nameTextView = (TextView) itemView.findViewById(R.id.contact_name); messageButton = (Button) itemView.findViewById(R.id.message_button); //messageButton.setOnClickListener(this); // Setup the click listener } } @Override public ContactsAdapter.ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) { Context context = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(context); // Inflate the custom layout View contactView = inflater.inflate(R.layout.item_contact, parent, false); // Return a new holder instance ViewHolder viewHolder = new ViewHolder(contactView); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { // Get the data model based on position Contact contact = mContacts.get(position); // Set item views based on your views and data model TextView textView = holder.nameTextView; textView.setText(contact.getName()); Button button = holder.messageButton; button.setText(contact.isOnline() ? "Message" : "Offline"); button.setEnabled(contact.isOnline()); } @Override public int getItemCount() { return mContacts.size(); } }
Binding the Adapter to the RecyclerView
public class MainActivity extends AppCompatActivity { ArrayList<Contact> contacts; RecyclerView rvContacts; Button addMoreButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rvContacts = (RecyclerView) findViewById(R.id.rvContacts); addMoreButton = (Button) findViewById(R.id.addContact); // Initialize contacts contacts = Contact.createContactsList(20); // Create adapter passing in the sample user data ContactsAdapter adapter = new ContactsAdapter(contacts); // Attach the adapter to the recyclerview to populate items rvContacts.setAdapter(adapter); // Set layout manager to position the items rvContacts.setLayoutManager(new LinearLayoutManager(this)); /* adapter.setOnItemClickListener(new ContactsAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { String name = contacts.get(position).getName(); Toast.makeText(MainActivity.this, name + " was clicked!", Toast.LENGTH_SHORT).show(); } }); */ addMoreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // record this value before making any changes to the existing list int curSize = adapter.getItemCount(); // Add a new contact // contacts.add(0, new Contact("Barney", true)); // Notify the adapter that an item was inserted at position 0 // adapter.notifyItemInserted(0); contacts.add(curSize, new Contact("Barney", true)); adapter.notifyItemInserted(curSize); } }); // That's all! } }
Notifying the Adapter
// Add a new contact contacts.add(0, new Contact("Barney", true)); // Notify the adapter that an item was inserted at position 0 adapter.notifyItemInserted(0);
Attaching Click Handlers using Listeners
Añadir la interface OnItemClickListener en ContactsAdapter.java
/***** Creating OnItemClickListener *****/ // Define the listener interface public interface OnItemClickListener { void onItemClick(View itemView, int position); } // Define listener member variable private OnItemClickListener listener; // Define the method that allows the parent activity or fragment to define the listener public void setOnItemClickListener(OnItemClickListener listener) { this.listener = listener; }
Añadir el listener al itemView en la clase ViewHolder en ContactsAdapter.java
// Provide a direct reference to each of the views within a data item // Used to cache the views within the item layout for fast access public class ViewHolder extends RecyclerView.ViewHolder { // Your holder should contain a member variable // for any view that will be set as you render a row public TextView nameTextView; public Button messageButton; // We also create a constructor that accepts the entire item row // and does the view lookups to find each subview public ViewHolder(View itemView) { // Stores the itemView in a public final member variable that can be used // to access the context from any ViewHolder instance. super(itemView); nameTextView = (TextView) itemView.findViewById(R.id.contact_name); messageButton = (Button) itemView.findViewById(R.id.message_button); //messageButton.setOnClickListener(this); // Setup the click listener itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Triggers click upwards to the adapter on click if (listener != null) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onItemClick(itemView, position); } } } }); } }
Añadir el listener al adapter en el MainActivity
adapter.setOnItemClickListener(new ContactsAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { String name = contacts.get(position).getName(); Toast.makeText(MainActivity.this, name + " was clicked!", Toast.LENGTH_SHORT).show(); } });
Mejora: Utilizar ViewBinding en el adapter
Ejercicio: PersonalNote (en el punto 4.3: RecyclerView de la unidad 2)
Más información:
Cómo crear listas dinámicas con RecyclerView
RecyclerView + CardView – Part 1: Layouts
RecyclerView + CardView – Part 2: Adapter
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.