[Android / Kotlin] RecyclerView

Subeen·2023년 3월 8일
0

Android

목록 보기
6/73
post-thumbnail

📍 RecyclerView란?

RecyclerView는 데이터 집합들을 각각의 개별 아이템 단위로 구성하여 화면에 출력해주는 뷰 그룹이다. 항목이 스크롤 되어 화면에서 벗어나더라도 뷰를 제거하지 않으며 화면에서 스크롤된 새 항목의 뷰를 재사용 한다. 앞서 포스팅 한 ListView의 단점을 보완하기 위해 만들어졌다.

📍 결과 동영상

📍 RecyclerView 구현하기

👩🏻‍💻 RecyclerView 생성하기

// activity_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>

    <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=".recyclerview.RecyclerViewActivity">

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

    </LinearLayout>
</layout>

👩🏻‍💻 데이터 클래스 생성하기

// RecyclerModel.kt
class RecyclerModel(
    val image: Int, val title: String, val content: String, val price: String
)

👩🏻‍💻 RecyclerView 아이템 생성하기

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

    <ImageView
        android:id="@+id/imageArea"
        android:layout_width="80dp"
        android:layout_height="80dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="10dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/titleArea"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center_vertical"
            android:textColor="@color/black"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/contentArea"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/priceArea"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/black"
            android:textSize="12sp"
            android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>

👩🏻‍💻 Adapter 생성하기

📌 ViewHolder

ViewHolder란 View를 보관하는 객체로 뷰를 재활용 하기 위해 각 요소를 저장해두고 사용한다.
ViewHolder는 Adapter 클래스 내에 내부 클래스로 생성한다.

inner class ViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        fun bindItems(items: RecyclerModel) {
            val imageArea = itemView.findViewById<ImageView>(R.id.imageArea)
            val titleArea = itemView.findViewById<TextView>(R.id.titleArea)
            val contentArea = itemView.findViewById<TextView>(R.id.contentArea)
            val priceArea = itemView.findViewById<TextView>(R.id.priceArea)

            imageArea.setImageResource(items.image)
            titleArea.text = items.title
            contentArea.text = items.content
            priceArea.text = items.price
        }
    }

📌 RecyclerAdapter

Adapter란 데이터 테이블을 목록 형태로 보여주기 위해 사용되는 것으로 데이터를 다양한 형식의 리스트로 보여주기 위해 데이터와 RecyclerView 사이에 존재하는 객체이다.
Adapter로 사용하기 위해서는 RecyclerView.Adapter를 상속 받아야 하는데 상속 받으려면 필수로 구현 되어야 하는 메서드들이 있다.

  • onCreateViewHolder() : View Holder를 생성하고 View를 붙여주는 역할의 메서드
  • getItemCount() : 데이터의 개수 반환하는 메서드
  • onBindViewHolder() : 생성된 View Holder에 데이터를 바인딩 해주는 메서드
// RecyclerAdapter.kt
class RecyclerAdapter(val items: MutableList<RecyclerModel>) :
    RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
    // View Holder를 생성하고 View를 붙여주는 역할의 메서드
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerAdapter.ViewHolder {
        val v =
            LayoutInflater.from(parent.context).inflate(R.layout.item_recyclerview, parent, false)
        return ViewHolder(v)
    }

    // 생성된 View Holder에 데이터를 바인딩 해주는 메서드 
    override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
        holder.bindItems(items[position])
    }

    // 데이터의 개수를 반환하는 메서드
    override fun getItemCount(): Int {
        return items.count()
    }

    // 화면에 표시 될 뷰를 저장하는 역할
    // View들을 재활용 하기 위해 각 요소를 저장해두고 사용한다.
    inner class ViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        fun bindItems(items: RecyclerModel) {
            val imageArea = itemView.findViewById<ImageView>(R.id.imageArea)
            val titleArea = itemView.findViewById<TextView>(R.id.titleArea)
            val contentArea = itemView.findViewById<TextView>(R.id.contentArea)
            val priceArea = itemView.findViewById<TextView>(R.id.priceArea)

            imageArea.setImageResource(items.image)
            titleArea.text = items.title
            contentArea.text = items.content
            priceArea.text = items.price
        }
    }
}

👩🏻‍💻 RecyclerView에 Adapter 연결하기

📌 Layout Manager

Recycler의 아이템의 배치와 재사용에 대한 정책을 결정하면 LayoutManager의 종류에 따라 아이템의 배치가 변경된다.
LayoutManager는 3가지 라이브러리를 제공한다.

  • LinearLayoutManager : 수평/수직으로 아이템을 배치한다.
  • GridLayoutManager : 격자 화면으로 아이템을 배치한다.
  • StaggeredGridLayoutManage : 높이가 불규칙한 격자 화면으로 아이템을 배치한다.
// RecyclerViewActivity.kt
class RecyclerViewActivity : AppCompatActivity() {
    lateinit var binding: ActivityRecyclerViewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_view)

        initRecycler()
    }

    private fun initRecycler() {
        val itemList = mutableListOf<RecyclerModel>()
        itemList.add(RecyclerModel(R.drawable.item_lv_01, "마리떼 프랑소와 저버", "CLASSIC LOGO CAP beige", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_02, "마리떼 프랑소와 저버", "CLASSIC LOGO WOOL ECO BAG blue", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_03, "마리떼 프랑소와 저버", "COLOR BLOCK SATIN SCRUNCHIE navy", "39,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_04, "마리떼 프랑소와 저버", "CLASSIC LOGO BACKPACK light blue", "159,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_05, "마리떼 프랑소와 저버", "CLASSIC LOGO COLOR BEANIE navy", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_06, "원브릴리언트", "Ivan-OB166-Black", "112,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_07, "시엔느", "Washing Lettering Ball Cap (Navy)", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_08, "마뗑킴", "ACCORDION WALLET IN WHITE", "88,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_09, "마리떼 프랑소와 저버", "CIRCLE LOGO SATIN HAIRBAND ivorye", "29,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_10, "리엔느와르","Dot Toggle Pearl Necklace (2color)", "57,000원"))

        val adapter = RecyclerAdapter(itemList)
        // Adapter 설정 
        binding.recyclerview.adapter = adapter
        // layyoutManager 설정
        binding.recyclerview.layoutManager = LinearLayoutManager(this)
    }
}

👩🏻‍💻 Click Event 구현하기

// RecyclerAdapter.kt
class RecyclerAdapter(val items: MutableList<RecyclerModel>) :
    RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
    // OnItemClickListener 인터페이스 선언
    interface onItemClickListener {
        fun onItemClick(position: Int)
    }
	// onItemClickListener 선언 
    private lateinit var itemClickListener: onItemClickListener
	// OnItemClickListener 등록 메서드 
    fun setItemClickListener(itemClickListener: onItemClickListener) {
        this.itemClickListener = itemClickListener
    }

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

    override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
    	// Listener에 onItemClick 등록
        holder.itemView.setOnClickListener {
            itemClickListener.onItemClick(position)
        }
        holder.bindItems(items[position])
    }

    override fun getItemCount(): Int {
        return items.count()
    }

    inner class ViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        fun bindItems(items: RecyclerModel) {
            val imageArea = itemView.findViewById<ImageView>(R.id.imageArea)
            val titleArea = itemView.findViewById<TextView>(R.id.titleArea)
            val contentArea = itemView.findViewById<TextView>(R.id.contentArea)
            val priceArea = itemView.findViewById<TextView>(R.id.priceArea)

            imageArea.setImageResource(items.image)
            titleArea.text = items.title
            contentArea.text = items.content
            priceArea.text = items.price
        }
    }
}
class RecyclerViewActivity : AppCompatActivity() {
    lateinit var binding: ActivityRecyclerViewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_view)

        initRecycler()
    }

    private fun initRecycler() {
        val itemList = mutableListOf<RecyclerModel>()
        itemList.add(RecyclerModel(R.drawable.item_lv_01, "마리떼 프랑소와 저버", "CLASSIC LOGO CAP beige", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_02, "마리떼 프랑소와 저버", "CLASSIC LOGO WOOL ECO BAG blue", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_03, "마리떼 프랑소와 저버", "COLOR BLOCK SATIN SCRUNCHIE navy", "39,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_04, "마리떼 프랑소와 저버", "CLASSIC LOGO BACKPACK light blue", "159,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_05, "마리떼 프랑소와 저버", "CLASSIC LOGO COLOR BEANIE navy", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_06, "원브릴리언트", "Ivan-OB166-Black", "112,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_07, "시엔느", "Washing Lettering Ball Cap (Navy)", "49,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_08, "마뗑킴", "ACCORDION WALLET IN WHITE", "88,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_09, "마리떼 프랑소와 저버", "CIRCLE LOGO SATIN HAIRBAND ivorye", "29,000원"))
        itemList.add(RecyclerModel(R.drawable.item_lv_10, "리엔느와르","Dot Toggle Pearl Necklace (2color)", "57,000원"))

        val adapter = RecyclerAdapter(itemList)
        binding.recyclerview.adapter = adapter
        binding.recyclerview.layoutManager = LinearLayoutManager(this)

		// adapter에 onItemClickListener 등록 
        adapter.setItemClickListener(object: RecyclerAdapter.onItemClickListener{
            override fun onItemClick(position: Int) {
                Toast.makeText(applicationContext, "RecyclerView: ${itemList[position].title}", Toast.LENGTH_SHORT).show()
            }
        })
    }
}

RecyclerView

profile
개발 공부 기록 🌱

0개의 댓글