[Android] RecyclerView 구현하기

안드로이드 애플리케이션을 개발하다보면 리스트 형태의 포맷을 많이 사용한다.
당장에 카카오톡만 보더라도 친구 목록, 대화 목록 등을 리스트 형태로 구현을 하고 있다.

이번에는 이러한 리스트를 표현하기에 좋은 안드로이드 요소인 RecyclerView의 구현 방법을 알아보려한다.

RecyclerView 구현 순서

RecyclerView의 구현은 다음의 순서로 진행된다.

  1. 레이아웃 구성
  2. 어댑터 구현
  3. 뷰홀더 구현
  4. 만들어진 어댑터를 RecyclerView에 할당

레이아웃 구성

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</androidx.constraintlayout.widget.ConstraintLayout>

이번 예제에서는 간단하게 이미지 뷰와 텍스트 뷰를 하나씩 갖는 뷰홀더를 구현한다.

view_holder_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/back_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/img_desc"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/img_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/back_img" />

</androidx.constraintlayout.widget.ConstraintLayout>

메인 액티비티에는 화면 전체를 덮고있는 RecyclerView를 만들고, RecyclerView의 아이템으로 ImageView와 TextView를 하나씩 갖고있는 레이아웃을 만든다

RecyclerView Adapter(어댑터) 구현

class MyAdapter(val init: ArrayList<Pair<String, String>> = ArrayList()) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

	private var data = init

	override fun getItemCount(): Int = data.size

	// 뷰홀더를 생성해서 리턴
	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
        MyViewHolder(ViewHolderItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))

	// 생성된 뷰홀더에 아이템을 바인드
	override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int){
		(holder as MyViewHolder).apply{
        		// 뷰홀더에서 구현한 bindItem메서드를 호출해 뷰홀더에 아이템을 바인딩
			bindItem(data.get(position))	
		}
	}

// ...
}

여기서는 3가지의 getItemCount(), onCreateViewHolder(), onBindViewHolder() 함수를 오버라이드해 구현해주어야 한다.

각 함수들은 순서대로 RecyclerView가 표현해야할 전체 데이터의 크기, RecyclerView에 붙여줄 ViewHolder 생성, 생성된 ViewHolder를 붙일때 처리 를 담당한다.

RecyclerView ViewHolder(뷰홀더) 구현

class MyAdapter:RecyclerView.Adapter(){

	// ...

	inner class MyViewHolder(val binding:ViewHolderItemBinding):RecyclerView.ViewHolder(binding.root){
		fun bindItem(item: Pair<String,String>){
			binding.imgDesc.text = item.second
			Glide.with(binding.root.context)
				.load(item.first)
				.into(binding.backImg)
		}
	}
}

innser class로 어댑터 클래스 내부에 뷰홀더 클래스를 작성하였다.

뷰홀더를 구현하는 부분에서는 뷰홀더가 RecyclerView에 바인딩 될 때 보여줄 아이템을 뷰홀더에 바인딩해주면 된다

RecyclerView에 어댑터 할당

class MainActivity:AppCompatActivity(){
	private val binding by lazy {
		ActivityMainBinding.inflate(layoutInflater)
	}
    
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(binding.root)
        
        	val data = arrayListOf<Pair<String, String>>(
            		Pair("https://picsum.photos/200", "설명1"),
			Pair("https://picsum.photos/200", "설명2"),
    	        	Pair("https://picsum.photos/200", "설명3")
		)
        
		binding.myRv.apply{
			adapter = MyAdapter()
			layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
		}
	}
}

위에서 작성한 어댑터를 레이아웃에서부터 가져온 RecyclerView의 어댑터로 할당해주고, layoutManager를 할당해주면 된다.

테스트

위 이미지에서 나오는것처럼 각 아이템 별 하나의 이미지뷰와 텍스트뷰를 갖고있으며, 이러한 아이템 3개가 리스트 형태로 나와있는 것을 볼 수 있다.

테스트에 사용한 데이터는 Lorem Picsum의 데이터를 이용하였으며, 본문에는 나와있지 않지만 아이템을 구별하기 위해 테두리를 나타내는 레이아웃 요소를 넣어주었다.

좋은 웹페이지 즐겨찾기