RecyclerView ile dinamik listeler oluşturma   Android Jetpack'in bir parçasıdır.

Yazma yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Oluşturma bölümünde düzenlerle nasıl çalışacağınızı öğrenin.

RecyclerView, büyük veri kümelerini verimli bir şekilde görüntülemeyi kolaylaştırır. Verileri siz sağlarsınız ve her öğenin nasıl görüneceğini tanımlarsınız. RecyclerView kitaplığı ise gerektiğinde öğeleri dinamik olarak oluşturur.

Adından da anlaşılacağı gibi RecyclerView, bu öğeleri yeniden kullanır. Bir öğe ekrandan kaydığında RecyclerView, görünümünü yok etmez. Bunun yerine, RecyclerView ekranda kaydırılan yeni öğeler için görünümü yeniden kullanır. RecyclerView, performansı ve uygulamanızın yanıt verme hızını artırır, güç tüketimini azaltır.

Önemli sınıflar

Dinamik listenizi oluşturmak için çeşitli sınıflar birlikte çalışır.

  • RecyclerView, verilerinize karşılık gelen görünümleri içeren ViewGroup'dir. Bu görünümün kendisi de bir görünüm olduğundan, RecyclerView düzeninize diğer kullanıcı arayüzü öğelerini eklediğiniz şekilde eklenir.

  • Listedeki her bir öğe, görünüm tutucu nesnesiyle tanımlanır. Görünüm tutucu oluşturulduğunda kendisiyle ilişkilendirilmiş herhangi bir veri yoktur. Görünüm tutucu oluşturulduktan sonra RecyclerView, onu verilerine bağlar. RecyclerView.ViewHolder öğesini genişleterek görünüm tutucuyu siz tanımlarsınız.

  • RecyclerView, adapter içindeki yöntemleri çağırarak görünümleri ister ve görünümleri verilerine bağlar. Adaptörü RecyclerView.Adapter öğesini genişleterek tanımlarsınız.

  • Düzen yöneticisi, listenizdeki öğeleri tek tek düzenler. RecyclerView kitaplığı tarafından sağlanan düzen yöneticilerinden birini kullanabilir veya kendi yöneticinizi tanımlayabilirsiniz. Tüm düzen yöneticileri, kitaplığın LayoutManager soyut sınıfına dayanır.

Tüm parçaların nasıl bir araya geldiğini RecyclerView örnek uygulamasında (Kotlin) veya RecyclerView örnek uygulamasında (Java) görebilirsiniz.

RecyclerView'ınızı uygulama adımları

RecyclerView'ı kullanacaksanız yapmanız gereken birkaç şey var. Bunlar, aşağıdaki bölümlerde ayrıntılı olarak açıklanmıştır.

  1. Listenin veya tablonun nasıl görüneceğine karar verin. Normalde, RecyclerView kitaplığının standart düzen yöneticilerinden birini kullanabilirsiniz.

  2. Listedeki her öğenin nasıl görüneceğini ve davranacağını tasarlayın. Bu tasarıma göre ViewHolder sınıfını genişletin. ViewHolder sürümünüz, liste öğeleriniz için tüm işlevleri sağlar. Görünüm tutucunuz, View öğesinin sarmalayıcısıdır ve bu görünüm RecyclerView tarafından yönetilir.

  3. Verilerinizi ViewHolder görünümleriyle ilişkilendiren Adapter tanımlayın.

Ayrıca gelişmiş özelleştirme seçenekleri de vardır. Bu seçenekler, RecyclerView'ınızı tam olarak ihtiyaçlarınıza göre uyarlamanıza olanak tanır.

Düzeninizi planlama

RecyclerView'ınızdaki öğeler bir LayoutManager sınıfına göre düzenlenir. RecyclerView kitaplığı, en yaygın düzen durumlarını ele alan üç düzen yöneticisi sağlar:

  • LinearLayoutManager öğeleri tek boyutlu bir listede düzenler.
  • GridLayoutManager Öğeleri iki boyutlu bir ızgarada düzenler:
    • Izgara dikey olarak düzenlenmişse GridLayoutManager, her satırdaki tüm öğelerin aynı genişlik ve yüksekliğe sahip olmasını sağlamaya çalışır ancak farklı satırlar farklı yüksekliklere sahip olabilir.
    • Izgara yatay olarak düzenlenmişse GridLayoutManager, her sütundaki tüm öğelerin aynı genişliğe ve yüksekliğe sahip olmasını sağlamaya çalışır ancak farklı sütunlar farklı genişliklere sahip olabilir.
  • StaggeredGridLayoutManager GridLayoutManager'e benzer ancak bir satırdaki öğelerin aynı yüksekliğe (dikey ızgaralar için) veya aynı sütundaki öğelerin aynı genişliğe (yatay ızgaralar için) sahip olmasını gerektirmez. Sonuç olarak, bir satır veya sütundaki öğeler birbirinden kayabilir.

Ayrıca tek tek öğelerin düzenini de tasarlamanız gerekir. Görünüm tutucuyu tasarlarken bu düzene ihtiyacınız vardır (bir sonraki bölümde açıklanmıştır).

Adaptörünüzü ve görünüm tutucunuzu uygulama

Düzeninizi belirledikten sonra Adapter ve ViewHolder öğelerini uygulamanız gerekir. Bu iki sınıf, verilerinizin nasıl görüntüleneceğini tanımlamak için birlikte çalışır. ViewHolder, listedeki bağımsız bir öğenin düzenini içeren bir View öğesinin sarmalayıcısıdır. Adapter, gerektiğinde ViewHolder nesneleri oluşturur ve bu görünümlerin verilerini de ayarlar. Görünümleri verileriyle ilişkilendirme işlemine bağlama adı verilir.

Adaptörünüzü tanımlarken üç temel yöntemi geçersiz kılarsınız:

  • onCreateViewHolder(): RecyclerView, yeni bir ViewHolder oluşturması gerektiğinde bu yöntemi çağırır. Yöntem, ViewHolder öğesini ve ilişkili View öğesini oluşturup başlatır ancak görünümün içeriğini doldurmaz. ViewHolder henüz belirli verilere bağlanmamıştır.

  • onBindViewHolder(): RecyclerView, bir ViewHolder öğesini verilerle ilişkilendirmek için bu yöntemi çağırır. Yöntem, uygun verileri getirir ve görünüm tutucunun düzenini doldurmak için bu verileri kullanır. Örneğin, RecyclerView bir ad listesi gösteriyorsa yöntem, listedeki uygun adı bulup görünüm tutucunun TextView widget'ını doldurabilir.

  • getItemCount(): RecyclerView, veri kümesinin boyutunu almak için bu yöntemi çağırır. Örneğin, bir adres defteri uygulamasında bu, toplam adres sayısı olabilir. RecyclerView, gösterilebilecek başka öğe kalmadığını belirlemek için bunu kullanır.

Aşağıda, veri listesi görüntüleyen iç içe yerleştirilmiş ViewHolder içeren basit bir bağdaştırıcıya dair tipik bir örnek verilmiştir. Bu durumda RecyclerView, basit bir metin öğeleri listesi görüntüler. Adaptöre, ViewHolder öğelerinin metnini içeren bir dizeler dizisi iletilir.

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;
    }
}

Her görünüm öğesinin düzeni, her zamanki gibi bir XML düzen dosyasında tanımlanır. Bu durumda, uygulamada şu şekilde bir text_row_item.xml dosyası bulunur:

<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>

Sonraki adımlar

Aşağıdaki kod snippet'inde RecyclerView öğesini nasıl kullanabileceğiniz gösterilmektedir.

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);

Kitaplık, uygulamayı özelleştirmek için birçok yöntem de sunar. Daha fazla bilgi için Gelişmiş RecyclerView özelleştirme konusuna bakın.

Uçtan uca ekranı etkinleştirin

RecyclerView için uçtan uca ekranı etkinleştirmek üzere şu adımları uygulayın:

  • enableEdgeToEdge() işlevini çağırarak geriye dönük uyumlu bir uçtan uca ekran ayarlayın.
  • Liste öğeleri başlangıçta sistem çubuklarıyla çakışıyorsa RecyclerView üzerinde iç kenarlar uygulayın. Bunu, android:fitsSystemWindows değerini true olarak ayarlayarak veya ViewCompat.setOnApplyWindowInsetsListener kullanarak yapabilirsiniz.
  • RecyclerView üzerinde android:clipToPadding değerini false olarak ayarlayarak liste öğelerinin kaydırma sırasında sistem çubuklarının altında çizilmesine izin verin.

Aşağıdaki videoda, kenardan kenara ekran özelliğinin devre dışı (sol) ve etkin (sağ) olduğu bir RecyclerView gösterilmektedir:

Örnek yerleştirme kodu:

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;
  }
);
  

RecyclerView XML'si:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:clipToPadding="false"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Ek kaynaklar

Android'de test etme hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın.

Örnek uygulamalar