staggeredgridlayoutmanager - recyclerview android studio ejemplo
Ejemplo simple de cuadrĂcula de Android usando RecyclerView con GridLayoutManager(como el antiguo GridView) (3)
Sé que
RecyclerView
ha reemplazado la funcionalidad de los antiguos
ListView
y
GridView
.
Estoy buscando un ejemplo muy básico que muestre una configuración de cuadrícula mínima usando
RecyclerView
.
No busco explicaciones largas de estilo tutorial, solo un ejemplo mínimo.
Me imagino que la cuadrícula más simple que imita el antiguo GridView consistiría en las siguientes características:
- múltiples celdas por fila
- vista única en cada celda
- responde a eventos de clic
Respuesta corta
Para aquellos que ya están familiarizados con la
configuración de un
RecyclerView
para hacer una lista
, la buena noticia es que hacer una cuadrícula es prácticamente lo mismo.
Solo usa un
GridLayoutManager
lugar de un
LinearLayoutManager
cuando configura
RecyclerView
.
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
Si necesita más ayuda que eso, consulte el siguiente ejemplo.
Ejemplo completo
El siguiente es un ejemplo mínimo que se verá como la imagen de abajo.
Comience con una actividad vacía.
Realizará las siguientes tareas para agregar la cuadrícula
RecyclerView
.
Todo lo que necesita hacer es copiar y pegar el código en cada sección.
Más tarde, puede personalizarlo para satisfacer sus necesidades.
- Agregar dependencias a gradle
- Agregue los archivos de diseño xml para la actividad y para la celda de cuadrícula
- Haga el adaptador RecyclerView
- Inicialice RecyclerView en su actividad
Actualizar dependencias de Gradle
Asegúrese de que las siguientes dependencias estén en el archivo
gradle.build
su aplicación:
compile ''com.android.support:appcompat-v7:27.1.1''
compile ''com.android.support:recyclerview-v7:27.1.1''
Puede actualizar los números de versión a lo que sea más actual .
Crear diseño de actividad
Agregue
RecyclerView
a su diseño xml.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvNumbers"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Crear diseño de celda de cuadrícula
Cada celda de nuestra cuadrícula
RecyclerView
solo tendrá un único
TextView
.
Cree un nuevo archivo de recursos de diseño.
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:padding="5dp"
android:layout_width="50dp"
android:layout_height="50dp">
<TextView
android:id="@+id/info_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/colorAccent"/>
</LinearLayout>
Crea el adaptador
RecyclerView
necesita un adaptador para llenar las vistas en cada celda con sus datos.
Crea un nuevo archivo java.
MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private String[] mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, String[] data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the cell layout from xml when needed
@Override
@NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each cell
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.myTextView.setText(mData[position]);
}
// total number of cells
@Override
public int getItemCount() {
return mData.length;
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.info_text);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
String getItem(int id) {
return mData[id];
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Notas
-
Aunque no es estrictamente necesario, incluí la funcionalidad para escuchar eventos de clic en las celdas.
Esto estaba disponible en el antiguo
GridView
y es una necesidad común. Puede eliminar este código si no lo necesita.
Inicializar RecyclerView en actividad
Agregue el siguiente código a su actividad principal.
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {
MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data to populate the RecyclerView with
String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.rvNumbers);
int numberOfColumns = 6;
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
adapter = new MyRecyclerViewAdapter(this, data);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
@Override
public void onItemClick(View view, int position) {
Log.i("TAG", "You clicked number " + adapter.getItem(position) + ", which is at cell position " + position);
}
}
Notas
-
Observe que la actividad implementa el
ItemClickListener
que definimos en nuestro adaptador. Esto nos permite manejar eventos de clic de celda enonItemClick
.
Terminado
Eso es. Debería poder ejecutar su proyecto ahora y obtener algo similar a la imagen en la parte superior.
Continuando
Esquinas redondeadas
Columnas autoajustables
Estudio adicional
- Android RecyclerView con GridView GridLayoutManager tutorial de ejemplo
- Ejemplo de diseño de cuadrícula de Android RecyclerView
- Aprenda RecyclerView con un ejemplo en Android
- RecyclerView: cuadrícula con encabezado
- Android GridLayoutManager con RecyclerView en diseño de materiales
- Comenzando con RecyclerView y CardView en Android
Aunque me gusta y aprecio
la respuesta de
Suragch
, me gustaría dejar una nota porque descubrí que codificar el
Adaptador
(
MyRecyclerViewAdapter
) para definir y exponer el método Listener
onItemClick
no es la mejor manera de hacerlo, debido a que no usa encapsulación de clase correctamente.
Entonces, mi sugerencia es dejar que el
Adaptador
maneje las operaciones de Escucha únicamente (¡ese es su propósito!) Y separarlas de la Actividad que usa el
Adaptador
(
MainActivity
).
Así es como establecería la clase Adaptador:
MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private String[] mData = new String[0];
private LayoutInflater mInflater;
// Data is passed into the constructor
public MyRecyclerViewAdapter(Context context, String[] data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// Inflates the cell layout from xml when needed
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
// Binds the data to the textview in each cell
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
String animal = mData[position];
holder.myTextView.setText(animal);
}
// Total number of cells
@Override
public int getItemCount() {
return mData.length;
}
// Stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView myTextView;
public ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.info_text);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
onItemClick(view, getAdapterPosition());
}
}
// Convenience method for getting data at click position
public String getItem(int id) {
return mData[id];
}
// Method that executes your code for the action received
public void onItemClick(View view, int position) {
Log.i("TAG", "You clicked number " + getItem(position).toString() + ", which is at cell position " + position);
}
}
Tenga en cuenta que el método
onItemClick
ahora definido en
MyRecyclerViewAdapter
es el lugar donde desea codificar sus tareas para el evento / acción recibido.
Solo hay que hacer un pequeño cambio para completar esta transformación: la
Actividad
ya no necesita implementar
MyRecyclerViewAdapter.ItemClickListener
, porque ahora eso lo hace completamente el
Adaptador
.
Esta sería entonces la modificación final:
MainActivity.java
public class MainActivity extends AppCompatActivity {
MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data to populate the RecyclerView with
String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};
// set up the RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rvNumbers);
int numberOfColumns = 6;
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
adapter = new MyRecyclerViewAdapter(this, data);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
}
Agregar dependencia RecyclerView dentro de build.gradle
compile ''com.android.support:recyclerview-v7:25.1.1''
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!--TODO(2): RecyclerView inside FrameLayout-->
<android.support.v7.widget.RecyclerView
android:id="@+id/rvStudents"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
>
</android.support.v7.widget.RecyclerView>
<!--TODO(3): Create one layout resource with item_student.xml name-->
</FrameLayout>
item_student.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#d2d2d2"
android:id="@+id/llItemStudents"
android:layout_margin="8dp"
>
<!--TODO(4): Remember to change the height of LinearLayout to wrap_content and also add its ID-->
<!--TODO(5): Add two TextView which will display student name and mobile number respectively-->
<TextView
android:id="@+id/tvStudentName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:padding="8dp"
android:textSize="25sp"
android:textStyle="bold"
android:textColor="@color/colorPrimary"
/>
<TextView
android:id="@+id/tvMobileNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:padding="8dp"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="@color/colorAccent"
/>
</LinearLayout>
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.text.Layout;
import java.util.ArrayList;
/*
* Demo Code of Recycler View
* Created on: 19th Feb, 2017
* Author Name: Rajat Talesra
* Company Name: WiseL
* This code is for Android Monk Campus Program.
*/
/*
* Recycler View is mainly used to show dynamic list of data.
* Many applications including Whatsapp, Facebook, Gmail, etc. used RecyclerView
*
* RecyclerView mainly uses two main components LayoutManager and Adapter
*
* LayoutManger: Helps to arrange data in LinearLayout or GridLayout
*
* Adapter: Helps to connect our recycler view with the custom layout and display data on screen
*
* In this demo we will display students list with their names and mobile numbers.
*/
public class MainActivity extends AppCompatActivity {
//TODO(6): Create arrayList for student names and ids.
ArrayList<String> namesArrayList = new ArrayList<>();
ArrayList<String> mobileArrayList = new ArrayList<>();
//TODO(7): Declare below mentioned components.
RecyclerView rvStudentsList;
RecyclerView.LayoutManager rvLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//TODO(10): Add data to arrayList
namesArrayList.add("Student 1");
namesArrayList.add("Student 2");
namesArrayList.add("Student 3");
namesArrayList.add("Student 4");
namesArrayList.add("Student 5");
namesArrayList.add("Student 6");
namesArrayList.add("Student 7");
namesArrayList.add("Student 8");
namesArrayList.add("Student 9");
namesArrayList.add("Student 10");
mobileArrayList.add("8766986401");
mobileArrayList.add("8766986402");
mobileArrayList.add("8766986403");
mobileArrayList.add("8766986404");
mobileArrayList.add("8766986405");
mobileArrayList.add("8766986406");
mobileArrayList.add("8766986407");
mobileArrayList.add("8766986408");
mobileArrayList.add("8766986409");
mobileArrayList.add("8766986410");
//TODO(9): Connect UI elements with java objects.
rvStudentsList = (RecyclerView) findViewById(R.id.rvStudents);
//User this to display items vertically
//rvLayoutManager = new LinearLayoutManager(this);
//User this to display items in Grid Layout with 2 columns
rvLayoutManager = new GridLayoutManager(this,2);
//TODO(10): Attach layoutManager to recycler view
rvStudentsList.setLayoutManager(rvLayoutManager);
/*
* Now we need to create one adapter, so that we can display data row wise
* For this we will create our custom adapter, i.e. StudentAdapter.java
*/
//TODO(11): Create new java class StudentAdapter.java
//TODO(16): Pass data to our custom adapter
StudentAdapter studentAdapter = new StudentAdapter(this,namesArrayList,mobileArrayList);
//TODO(17): Attach studentAdapter to recycler view
rvStudentsList.setAdapter(studentAdapter);
//TODO(18): Run your app.
}
}
StudentAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
//TODO(12): StudentAdapter extends RecyclerView Adapter with ViewHolder class
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.ViewHolder> {
//TODO(13): Create two empty arrayList and one context variable;
Context mainActivityContext;
ArrayList<String> namesArrayList = new ArrayList<>();
ArrayList<String> mobileArrayList = new ArrayList<>();
//TODO(14): Create one constructor with three parameters which will passed from MainActivity class
public StudentAdapter(Context mainActivityContext, ArrayList<String> namesArrayList, ArrayList<String> mobileArrayList) {
this.mainActivityContext = mainActivityContext;
this.namesArrayList = namesArrayList;
this.mobileArrayList = mobileArrayList;
}
//TODO(15): Complete each method as mentioned below
@Override
public StudentAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Used to connect our custom UI to our recycler view
View v = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.item_student, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(StudentAdapter.ViewHolder holder, int position) {
//Used to set data in each row of recycler view
String currentName = namesArrayList.get(position);
String currentMobileNumber = mobileArrayList.get(position);
holder.tvName.setText(currentName);
holder.tvMobileNumber.setText(currentMobileNumber);
}
@Override
public int getItemCount() {
//Returns total number of rows inside recycler view
return namesArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
//Used to work with the elements of our custom UI.
LinearLayout llItemStudents;
TextView tvName;
TextView tvMobileNumber;
public ViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvStudentName);
tvMobileNumber = (TextView) itemView.findViewById(R.id.tvMobileNumber);
llItemStudents = (LinearLayout) itemView.findViewById(R.id.llItemStudents);
llItemStudents.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mainActivityContext,
"You clicked item number: "+ getAdapterPosition(),
Toast.LENGTH_SHORT).show();
}
});
}
}
}
Visite también el documento oficial.