Créer des listes dynamiques avec RecyclerView Inclus dans Android Jetpack.
RecyclerView permet d'afficher efficacement de grands ensembles de données. Vous fournissez les données et définissez l'apparence de chaque élément, et la bibliothèque RecyclerView crée les éléments de manière dynamique lorsque cela est nécessaire.
Comme son nom l'indique, RecyclerView recycle ces éléments individuels. Lorsqu'un élément disparaît de l'écran, RecyclerView ne détruit pas sa vue. Au lieu de cela, RecyclerView réutilise la vue pour les nouveaux éléments qui s'affichent à l'écran. RecyclerView améliore les performances et la réactivité de votre application, et réduit la consommation d'énergie.
Classes clés
Plusieurs classes fonctionnent ensemble pour créer votre liste dynamique.
RecyclerViewest l'ViewGroupqui contient les vues correspondant à vos données. Il s'agit d'une vue en soi. Vous ajoutez doncRecyclerViewà votre mise en page comme vous le feriez pour n'importe quel autre élément d'interface utilisateur.Chaque élément de la liste est défini par un objet ViewHolder. Lors de sa création, le conteneur de vue n'est associé à aucune donnée. Une fois le conteneur de vue créé, le
RecyclerViewl'associe à ses données. Vous définissez le conteneur de vue en étendantRecyclerView.ViewHolder.RecyclerViewdemande des vues et les associe à leurs données en appelant des méthodes dans l'adaptateur. Vous définissez l'adaptateur en étendantRecyclerView.Adapter.Le gestionnaire de mise en page organise les éléments individuels de votre liste. Vous pouvez utiliser l'un des gestionnaires de mise en page fournis par la bibliothèque RecyclerView ou définir le vôtre. Les gestionnaires de mise en page sont tous basés sur la classe abstraite
LayoutManagerde la bibliothèque.
Vous pouvez voir comment tous les éléments s'assemblent dans l'application exemple RecyclerView (Kotlin) ou l'application exemple RecyclerView (Java).
Étapes d'implémentation de votre RecyclerView
Si vous souhaitez utiliser RecyclerView, vous devez effectuer quelques opérations, qui sont expliquées en détail dans les sections suivantes.
Choisissez l'apparence de la liste ou de la grille. En règle générale, vous pouvez utiliser l'un des gestionnaires de mises en page standards de la bibliothèque RecyclerView.
Concevez l'apparence et le comportement de chaque élément de la liste. En fonction de cette conception, étendez la classe
ViewHolder. Votre version deViewHolderfournit toutes les fonctionnalités pour les éléments de votre liste. Votre conteneur de vue est un wrapper autour d'unView, et cette vue est gérée parRecyclerView.Définissez le
Adapterqui associe vos données aux vuesViewHolder.
Il existe également des options de personnalisation avancées qui vous permettent d'adapter votre RecyclerView à vos besoins exacts.
Planifier votre mise en page
Les éléments de votre RecyclerView sont organisés par une classe LayoutManager. La bibliothèque RecyclerView fournit trois gestionnaires de mises en page, qui gèrent les situations de mise en page les plus courantes :
LinearLayoutManagerorganise les éléments dans une liste unidimensionnelle.GridLayoutManagerorganise les éléments dans une grille bidimensionnelle :- Si la grille est disposée verticalement,
GridLayoutManageressaie de faire en sorte que tous les éléments de chaque ligne aient la même largeur et la même hauteur, mais les différentes lignes peuvent avoir des hauteurs différentes. - Si la grille est disposée horizontalement,
GridLayoutManageressaie de faire en sorte que tous les éléments de chaque colonne aient la même largeur et la même hauteur, mais différentes colonnes peuvent avoir des largeurs différentes.
- Si la grille est disposée verticalement,
StaggeredGridLayoutManagerest semblable àGridLayoutManager, mais ne nécessite pas que les éléments d'une ligne aient la même hauteur (pour les grilles verticales) ou que les éléments d'une même colonne aient la même largeur (pour les grilles horizontales). Par conséquent, les éléments d'une ligne ou d'une colonne peuvent se retrouver décalés les uns par rapport aux autres.
Vous devez également concevoir la mise en page des éléments individuels. Vous aurez besoin de cette mise en page lorsque vous concevrez le conteneur de vue, comme décrit dans la section suivante.
Implémenter votre adaptateur et votre conteneur de vue
Une fois que vous avez déterminé votre mise en page, vous devez implémenter vos Adapter et ViewHolder. Ces deux classes fonctionnent ensemble pour définir l'affichage de vos données. ViewHolder est un wrapper autour d'un View qui contient la mise en page d'un élément individuel de la liste. Adapter crée des objets ViewHolder si nécessaire et définit également les données de ces vues. Le processus d'association des vues à leurs données est appelé liaison.
Lorsque vous définissez votre adaptateur, vous remplacez trois méthodes clés :
onCreateViewHolder():RecyclerViewappelle cette méthode chaque fois qu'il doit créer unViewHolder. La méthode crée et initialise l'objetViewHolderet l'objetViewassocié, mais elle ne remplit pas le contenu de la vue. L'objetViewHoldern'a pas encore été lié à des données spécifiques.onBindViewHolder():RecyclerViewappelle cette méthode pour associer unViewHolderà des données. La méthode récupère les données appropriées et les utilise pour remplir la mise en page du conteneur de vue. Par exemple, siRecyclerViewaffiche une liste de noms, la méthode peut trouver le nom approprié dans la liste et renseigner le widgetTextViewdu conteneur de vue.getItemCount():RecyclerViewappelle cette méthode pour obtenir la taille de l'ensemble de données. Par exemple, dans une application de carnet d'adresses, il peut s'agir du nombre total d'adresses. RecyclerView l'utilise pour déterminer quand il n'y a plus d'éléments à afficher.
Voici un exemple typique d'adaptateur simple avec un ViewHolder imbriqué qui affiche une liste de données. Dans ce cas, RecyclerView affiche une simple liste d'éléments de texte. Un tableau de chaînes contenant le texte des éléments ViewHolder est transmis à l'adaptateur.
Kotlin
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
Java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
La mise en page de chaque élément de vue est définie dans un fichier de mise en page XML, comme d'habitude.
Dans ce cas, l'application dispose d'un fichier text_row_item.xml comme celui-ci :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
Étapes suivantes
L'extrait de code suivant montre comment utiliser RecyclerView.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
La bibliothèque propose également de nombreuses façons de personnaliser votre implémentation. Pour en savoir plus, consultez Personnalisation avancée de RecyclerView.
Activer l'affichage de bord à bord
Pour activer l'affichage de bord à bord pour un RecyclerView, procédez comme suit :
- Configurez un affichage de bord à bord rétrocompatible en appelant
enableEdgeToEdge(). - Si les éléments de la liste chevauchent initialement les barres système, appliquez des encarts sur le
RecyclerView. Pour ce faire, définissezandroid:fitsSystemWindowssurtrueou utilisezViewCompat.setOnApplyWindowInsetsListener. - Autorisez l'affichage des éléments de la liste sous les barres système lors du défilement en définissant
android:clipToPaddingsurfalsesurRecyclerView.
La vidéo suivante montre un RecyclerView avec l'affichage de bord à bord désactivé (à gauche) et activé (à droite) :
Exemple de code d'encart :
Kotlin
ViewCompat.setOnApplyWindowInsetsListener( findViewById(R.id.my_recycler_view) ) { v, insets -> val innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "or WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ) v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom) insets }
Java
ViewCompat.setOnApplyWindowInsetsListener( activity.findViewById(R.id.my_recycler_view), (v, insets) -> { Insets innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "| WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ); v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom ); return insets; } );
Le fichier XML RecyclerView :
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Ressources supplémentaires
Pour en savoir plus sur les tests sur Android, consultez les ressources suivantes.