Grundlegende Verwendung von RecycleView

Vorwort

Um die schlechte Skalierbarkeit von ListView und die Notwendigkeit einer manuellen Leistungsoptimierung zu lösen, stellt Android eine Scroll-Komponente RecycleView bereit. Dieser Blog wird verwendet, um die Verwendung von RecycleView zu klären .

Vorteile von RecycleView

  1. RecycleView verarbeitet nur Elemente, die derzeit auf dem Bildschirm angezeigt werden. Wenn die Liste 1000 Elemente enthält und auf der Seite nur 10 davon angezeigt werden, verarbeitet RecycleView nur diese 10 Elemente
  2. RecycleView recycelt seine Ansicht, wenn ein Element vom Bildschirm verschiebt. Dieses Element wird recycelt und zum Füllen des Inhalts neu eingegebener Bildschirme verwendet.
  3. Wenn sich ein Element ändert, wird nur das geänderte Element neu lackiert.

Anweisungen

Abhängigkeiten hinzufügen

Erstellen Sie eine neue UiWidgetTest-Datei

Fügen Sie den folgenden Inhalt zu den Abhängigkeiten von build.gradle (Moudule) hinzu , und die neueste Version kann in Recyclerview | Android Developers angezeigt werden .

implementation("androidx.recyclerview:recyclerview:1.2.1")
// For control over item selection of both touch and mouse driven selection
implementation("androidx.recyclerview:recyclerview-selection:1.1.0")

Klicken Sie nach dem Hinzufügen des Codes auf „Jetzt synchronisieren“, um Gradle erneut zu synchronisieren.

Bild-20220513195831301

Passen Sie die RecycleView-Schnittstelle an

Ändern Sie den Code in Activity_main.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Erstellen Sie im Layout-Ordner eine neue Datei „girl_item.xml“. Diese Datei wird zum Anzeigen jedes Datenelements in RecycleView verwendet.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <ImageView
        android:id="@+id/girlImage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp" />

    <TextView
        android:id="@+id/fruitName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp" />

</LinearLayout>

Dieses Unterlayout ist sehr einfach, nur ein Bild und eine Beschriftung

Bereiten Sie Bildressourcen vor

Bereiten Sie einige Bildressourcen vor und legen Sie sie im Ordner res -> drawable ab

Bild-20220513203128085

Entitätsklassen erstellen

Die Elemente in jedem Element in RecycleView stammen von einem Objekt, das heißt, die Daten in RecycleView stammen aus einer Sammlung.

Erstellen Sie eine neue Girl-Klasse. Der Code lautet wie folgt.

package com.example.uiwidgettest

class Girl(val name: String,val imageId:Int)

imageId ist vom Typ Int und speichert die Ressourcen-ID des entsprechenden Bildes.

AdapterAdapter

Wie bereits erwähnt, ist die Datenquelle in RecycleView List<Object>, Arrays können jedoch nicht direkt auf RecycleView angewendet werden.

Angenommen, das Array ist ein herkömmliches Micro-USB-Datenkabel und RecycleView ist ein Typ-C-Mobiltelefon.

Micro-USB-Datenkabel können nicht auf Typ-C-Mobiltelefonen verwendet werden, daher ist ein Adapter erforderlich, um Micro-USB in Typ-C umzuwandeln

Adapter wird in einen Adapter übersetzt, der verwendet wird, um die List-Sammlung an die verfügbaren Typen von RecycleView anzupassen.

Erstellen Sie eine neue GirlAdapter-Klasse, lassen Sie sie die RecycleView.Adapter-Klasse erben und legen Sie das Paradigma als GirlAdapter.ViewHolder fest

package com.example.uiwidgettest

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class GirlAdapter(private val girls: List<Girl>) : RecyclerView.Adapter<GirlAdapter.ViewHolder>() {
    
    

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
    
        val girlName: TextView = view.findViewById(R.id.girlName)
        val girlImage: ImageView = view.findViewById(R.id.girlImage)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    
    
        val view = LayoutInflater.from(parent.context).inflate(R.layout.girl_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    
    
        val girl = girls[position]
        holder.girlName.text = girl.name
        holder.girlImage.setImageResource(girl.imageId)
    }

    override fun getItemCount() = girls.size
}

Code-Analyse

  • Der GirlAdapter-Parameter ist die Girl-Sammlung, und GirlAdapter konvertiert diese Sammlung in die verfügbaren Typen von RecycleView
  • ViewHolder wird als View-Halter übersetzt, der zur Beschreibung der Daten in einer untergeordneten Ansicht und ihrer Positionsinformationen in RecycleView verwendet wird
  • Die innere Klasse ViewHolder erbt von RecycleView.ViewHolder(). ViewHolder erfordert ein View-Objekt ungleich Null als Parameter
  • RecycleView.Adapter ist eine abstrakte Klasse. Um diese Klasse zu erben, müssen die Methoden onCreateViewHolder (), onBindViewHolder () und getItemCount () implementiert werden
  • Mit onCreateViewHolder() wird ein ViewHolder erstellt, und die Parameteransicht ist die Klasse, die dem Unterelement-XML entspricht. Laden Sie girl_item als View-Klasse mit dem Layout-Loader
  • onBindViewHolder() wird verwendet, um den untergeordneten Elementen von RecycleView Werte zuzuweisen, und wird ausgeführt, wenn jedes untergeordnete Element in den Bildschirm gescrollt wird . Rufen Sie die Objektinstanz entsprechend der Position ab und legen Sie die Daten auf das Element von ViewHolder fest.
  • getItemCount() wird verwendet, um RecycleView mitzuteilen, wie viele Unterelemente es gibt.

Verwenden Sie RecycleView

Ändern Sie den Code in MainActivity

package com.example.uiwidgettest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.uiwidgettest.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    
    
    private val girls = ArrayList<Girl>()

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initGirls()
        val layoutManager = LinearLayoutManager(this)
        binding.recycleView.layoutManager = layoutManager
        val girlAdapter = GirlAdapter(girls)
        binding.recycleView.adapter = girlAdapter
    }

    private fun initGirls() {
    
    
        repeat(3) {
    
    
            girls.add(Girl("Girl1", R.drawable.girl1))
            girls.add(Girl("Girl2", R.drawable.girl2))
            girls.add(Girl("Girl3", R.drawable.girl3))
            girls.add(Girl("Girl4", R.drawable.girl4))
            girls.add(Girl("Girl5", R.drawable.girl5))
        }
    }
}

Im Code wird zunächst eine Sammlung von Mädchen initialisiert, dann in der Methode onCreate() ein LinearLayoutManager-Objekt erstellt und auf RecycleView gesetzt.

Mit layoutManager wird das Layout von RecycleView festgelegt, und LinearLayoutManager repräsentiert das lineare Layout.

Erstellen Sie eine GirlAdapter-Instanz und übergeben Sie die Girls-Sammlung an den Konstruktor des GirlAdapter.

Rufen Sie abschließend die setAdapter()-Methode von RecycleView auf, um die Adaptereinstellung abzuschließen.

Führen Sie bisher die App aus, um den laufenden Effekt von RecycleView zu sehen.

Implementieren Sie horizontales Scrollen und Wasserfall-Layout

Ein weiterer Vorteil von RecycleView gegenüber ListView besteht darin, dass horizontales Scrollen problemlos implementiert und das Layout geändert werden kann.

Dank LayoutManager können das Layout und die Bildlaufrichtung von RecycleView einfach durch Festlegen von LayoutManager geändert werden.

Implementieren Sie horizontales Scrollen

Ändern Sie girl_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="80dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/girlImage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp" />

    <TextView
        android:id="@+id/girlName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp" />

</LinearLayout>

Ändern Sie das LinearLayout in „Vertikal“, die Breite in 80 dp und die Höhe in „wrap_content“.

Da hier horizontales Scrollen implementiert ist, ist es am besten, ihre Breiten konsistent zu halten, damit sie schöner aussehen.

Die layout_gravity der beiden untergeordneten Ansichten wird in „center_horizontal“ geändert.

Legen Sie die Anordnungsrichtung des LayoutManagers in MainActivity fest

layoutManager.orientation = LinearLayoutManager.HORIZONTAL

Implementieren Sie das Wasserfall-Layout

Das Wasserfall-Layout ist eine ungleichmäßige Anordnung mehrerer Reihen gleicher Breite und unterschiedlicher Höhenelemente , wie in der folgenden Abbildung dargestellt:

Wasserfall-Layout

Ändern Sie zunächst die Layoutdatei des untergeordneten Elements girl_item.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:layout_margin="5dp">

    <ImageView
        android:id="@+id/girlImage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp" />

    <TextView
        android:id="@+id/girlName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp" />

</LinearLayout>

Im Code wurden folgende Änderungen vorgenommen:

  1. Die Breite von LinearLayout wurde von 80 dp in match_parent geändert. Da die Breite des Wasserfalls automatisch an die Anzahl der Spalten im Layout angepasst wird , handelt es sich nicht um einen festen Wert.
  2. Damit jedes Kind nicht so überfüllt aussieht, ist für das LinearLayout ein Spielraum von 5 dp festgelegt.
  3. Ändern Sie die Ausrichtungseigenschaft von TextView von Mitte nach Links. Weil die Länge des Textes später geändert wird, sodass jedes untergeordnete Element nicht die gleiche Höhe hat.
package com.example.uiwidgettest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.example.uiwidgettest.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    
    
    private val girls = ArrayList<Girl>()

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initGirls()
        val layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
        binding.recycleView.layoutManager = layoutManager
        val girlAdapter = GirlAdapter(girls)
        binding.recycleView.adapter = girlAdapter
    }

    private fun initGirls() {
    
    
        repeat(5) {
    
    
            girls.add(Girl(getRandomName("Girl1"), R.drawable.girl1))
            girls.add(Girl(getRandomName("Girl2"), R.drawable.girl2))
            girls.add(Girl(getRandomName("Girl3"), R.drawable.girl3))
            girls.add(Girl(getRandomName("Girl4"), R.drawable.girl4))
            girls.add(Girl(getRandomName("Girl5"), R.drawable.girl5))
        }
    }

    private fun getRandomName(name: String): String {
    
    
        val n = (1..20).random()
        val builder = StringBuilder()
        repeat(n){
    
    
                builder.append(name)
        }
        return builder.toString()
    }
}

Ändern Sie zunächst das Layout des LayoutManagers vom linearen Layout zum Wasserfall-Flow-Layout

val layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)

Der erste Parameter von StaggeredGridLayoutManager wird verwendet, um die Anzahl der Spalten des Layouts anzugeben , und der zweite Parameter wird verwendet, um die Anordnungsrichtung des Layouts anzugeben .

Zweitens wird eine getRandomName()-Methode hinzugefügt, damit verschiedene Elemente unterschiedliche Höhen haben.

private fun getRandomName(name: String): String {
    
    
        val n = (1..20).random() 	// 通过随机数的方式拓展名字的长度
        val builder = StringBuilder()
        repeat(n){
    
     // 将原来的名字重复 n 次
                builder.append(name)
        }
        return builder.toString()
    }

Klicken Sie auf das Ereignis von RecycleView

Ändern Sie den Code der Adapterklasse GirlAdapter

package com.example.uiwidgettest

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView

class GirlAdapter(private val girls: List<Girl>) : RecyclerView.Adapter<GirlAdapter.ViewHolder>() {
    
    

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
    
        val girlName: TextView = view.findViewById(R.id.girlName)
        val girlImage: ImageView = view.findViewById(R.id.girlImage)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    
    
        val view = LayoutInflater.from(parent.context).inflate(R.layout.girl_item, parent, false)
        val viewHolder = ViewHolder(view)
        viewHolder.girlName.setOnClickListener{
    
    
            val position = viewHolder.adapterPosition
            val girl = girls[position]
            Toast.makeText(parent.context,"你点击了文字 ${
      
      girl.name}$",Toast.LENGTH_SHORT).show()
        }
        viewHolder.girlImage.setOnClickListener{
    
    
            val position = viewHolder.adapterPosition
            val girl = girls[position]
            Toast.makeText(parent.context,"你点击了图片 ${
      
      girl.name}$",Toast.LENGTH_SHORT).show()
        }
        return viewHolder
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    
    
        val girl = girls[position]
        holder.girlName.text = girl.name
        holder.girlImage.setImageResource(girl.imageId)
    }

    override fun getItemCount() = girls.size
}

Registrieren Sie in der Methode onCreateViewHolder() das Klickereignis für die Unteransicht des Viewholders.

viewholder.adapterPosition wird verwendet, um die Position des untergeordneten Elements zu ermitteln, und die Objekte im Array können entsprechend der Position manipuliert werden .

Diese Methode ist jedoch veraltet. Denn wenn der Adapter verschachtelt ist, führt der Aufruf dieser Methode zu Mehrdeutigkeiten .

Google hat zwei neue Methoden getBindingAdapterPosition() und getAbsoluteAdapterPosition() vorgeschlagen, um das Problem zu lösen

Verwechslungsproblem bei der Verschachtelung des Adapters.

// 如果你希望访问的是 Adapter 中内容的位置 ,使用 bindingAdapterPosition
val position = viewHolder.bindingAdapterPosition
// 如果你希望访问的是 适配器相对于 RecycleView 的位置,使用 bindingAdapterPosition
val position = viewHolder.absoluteAdapterPosition

Supongo que te gusta

Origin blog.csdn.net/jiaweilovemingming/article/details/124843540
Recomendado
Clasificación