리스트뷰 그리는 방법3 : RecyclerView

2021. 5. 28. 23:53

리스트뷰는 유사하게 반복되는 뷰를 그리기 위한 도구이다.

 

리스트뷰를 그리는 방법에는 세가지가 있다.

1. addView : 실제로 리스트뷰를 그리기 위해 잘 사용되지 않는다.

2. ListView : 예전에 많이 사용되었다.

3. RecycleView : 최근에 가장 많이 사용되고있고 가장 효율이 높다.

 

위 세가지를 구현하는 방법 중 RecyclerView에 대해 알아본다.

 

RecyclerView

recyclerview는 listview의 개선판으로 Adapter를 이용하며 ViewHolder 개념을 포함한다.

recyclerview에서는 layoutmanager를 관리하여

linear, grid, staggeredgrid 등 유연하게 다양한 레이아웃을 만들 수 있다.

 

recyclerView를 만들기 전 app단의 build.gradle에서 recyclerview를 추가한다.

implementation "androidx.recyclerview:recyclerview:1.2.0"

 

XML 파일에는 recyclerview를 만든다

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".AddViewActivity">

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

</LinearLayout>

 

activity에서 RecyclerViewAdapter를 만든다.

RecyclerViewAdapter에서는 ViewHolder를 만들고 이를 상속받는다.

 

ViewHolder에서는 init에서 findViewById를 이용하여 뷰를 생성하고 

세개의 메소드를 override한다.

  • onCreateViewHolder() : 뷰를 만들어 ViewHolder에 넣어 return한다.
  • getItemCout() : 아이템 리스트 사이즈를 return한다.
  • onBindViewHolder() : ViewHolder의 태그를 재활용하여 holder에 있는 뷰에 그려넣어준다.
class RecyclerViewAdapter(
    val itemList : ArrayList<CarForList>,
    val inflater : LayoutInflater
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val carName: TextView
        val carEngine: TextView

        init{
            carName = itemView.findViewById(R.id.car_name)
            carEngine = itemView.findViewById(R.id.car_engine)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = inflater.inflate(R.layout.item_view, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return itemList.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.carName.text = itemList[position].name
        holder.carEngine.text = itemList[position].engine
    }
}
  1. onCreateViewHolder가 호출이 되면 아이템 하나가 들어갈 view를 만들어 ViewHolder에 넣어 return하고
  2. 호출된 ViewHolder에서 itemView로 view를 받아 만들면 findViewById를 통해 뷰를 세팅한다.
  3. onBindViewHolder가 호출이 되면 세팅된 뷰를 불러 값을 넣어준다.

 

onCreate()에서는 adapter와 layoutManager를 만들어 recyclerview에 넣어준다.

LinearLayoutManager 대신 다른 레이아웃 매니저를 넣어도 가능하다.

private lateinit var binding: ActivityRecyclerviewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 아이템 리스트 준비
        val carList = ArrayList<CarForList>()
        for (i in 1 .. 10){
            carList.add(CarForList(""+i+"번째 자동차", ""+i+"순위 엔진"))
        }

        val adapter = RecyclerViewAdapter(carList, LayoutInflater.from(this@RecyclerViewActivity))
        binding.recyclerviewContainer.adapter = adapter
        binding.recyclerviewContainer.layoutManager = LinearLayoutManager(this@RecyclerViewActivity)

    }

 

✔ 리스너 적용하기

ViewHolder 클래스의 init 부분에 리스너를 달아준다.

이 때, ViewHolder 클래스 밖의 클래스인 RecyclerViewAdapter의 itemList를 사용해야하기 때문에

ViewHolder 클래스를 inner class로 바꿔준다.

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val carName: TextView
        val carEngine: TextView

        init{
            carName = itemView.findViewById(R.id.car_name)
            carEngine = itemView.findViewById(R.id.car_engine)
            itemView.setOnClickListener{
                val position: Int = bindingAdapterPosition
                val enginName = itemList[position].engine
                Log.d("engine", enginName)
            }
        }
    }

 

정리된 최종 activity는 다음과 같다.

package com.example.prac_android

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.prac_android.databinding.ActivityListviewBinding
import com.example.prac_android.databinding.ActivityRecyclerviewBinding

class RecyclerViewActivity : AppCompatActivity() {
    private lateinit var binding: ActivityRecyclerviewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 아이템 리스트 준비
        val carList = ArrayList<CarForList>()
        for (i in 1 .. 10){
            carList.add(CarForList(""+i+"번째 자동차", ""+i+"순위 엔진"))
        }

        val adapter = RecyclerViewAdapter(carList, LayoutInflater.from(this@RecyclerViewActivity))
        binding.recyclerviewContainer.adapter = adapter
        binding.recyclerviewContainer.layoutManager = LinearLayoutManager(this@RecyclerViewActivity)

    }
}

class RecyclerViewAdapter(
    val itemList : ArrayList<CarForList>,
    val inflater : LayoutInflater
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val carName: TextView
        val carEngine: TextView

        init{
            carName = itemView.findViewById(R.id.car_name)
            carEngine = itemView.findViewById(R.id.car_engine)
            itemView.setOnClickListener{
                val position: Int = bindingAdapterPosition
                val enginName = itemList[position].engine
                Log.d("engine", enginName)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = inflater.inflate(R.layout.item_view, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return itemList.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.carName.text = itemList[position].name
        holder.carEngine.text = itemList[position].engine
    }
}

 

728x90

'💻개발 > Android' 카테고리의 다른 글

Async  (0) 2021.05.30
TabLayout과 Pager  (0) 2021.05.29
리스트뷰 그리는 방법2 : ListView  (0) 2021.05.28
리스트뷰 그리는 방법1 : addView  (0) 2021.05.28
Framework 와 Library  (0) 2021.05.28

BELATED ARTICLES

more