본문 바로가기
개발

안드로이드 코틀린 recyclerview 만들기

by kks950115 2024. 1. 10.
728x90

이전 글에서 리샤이클러 뷰의 개념에 대해서 설명했었는데 이제 구현해볼 차례다. 원래는 그 날 다 쓸까 했었는데 글이 너무 길어질거 같아서 나눴다. 아래 코드는 부트캠프 과제로 했던 코드 중 일부이다. 

 

 

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
    
    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_mainList"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent" />
            
</androidx.constraintlayout.widget.ConstraintLayout>

 

main_list_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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
     >

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraintLayout3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="15dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">


        <androidx.cardview.widget.CardView
            android:id="@+id/iv_item_pic"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            app:cardCornerRadius="20dp"
            app:layout_constraintEnd_toStartOf="@+id/linearLayout"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintHorizontal_weight="1"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" >
            <ImageView
                android:id="@+id/iv_item_pic2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:background="#cccccc"
                android:scaleType="centerCrop"
                android:src="@drawable/question"
                />

        </androidx.cardview.widget.CardView>

        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="15dp"
            android:orientation="vertical"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_weight="2"
            app:layout_constraintStart_toEndOf="@+id/iv_item_pic"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:id="@+id/tv_item_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:maxLines="2"
                android:text="울산 동해오션뷰 60평 복층 펜트파우스 1일 숙박권 펜션 힐링 숙수 판매합니다."
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/tv_address"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="수원시 영통구 원천동"
                android:textColor="#777777"
                android:textSize="16sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/tv_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="50,000원"
                android:textSize="18sp"
                android:textStyle="bold" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="10dp"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent">

            <ImageView
                android:id="@+id/iv_comment"
                android:layout_width="18dp"
                android:layout_height="18dp"
                android:layout_marginEnd="5dp"
                android:src="@drawable/chat"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:tint="@color/black" />

            <TextView
                android:id="@+id/tv_commentCount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="15dp"
                android:text="25" />

            <ImageView
                android:id="@+id/iv_like"
                android:layout_width="18dp"
                android:layout_height="18dp"
                android:layout_marginEnd="5dp"
                android:src="@drawable/heart"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:tint="@color/black" />

            <TextView
                android:id="@+id/tv_likeCount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="25" />
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#cccccc"
        app:layout_constraintTop_toBottomOf="@+id/constraintLayout3" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

이 레이아웃이 리사이클러 뷰에 뜰 것이다.

값을 바꿔줘야하는 뷰에는 아이디를 설정해준다. 그래야 동적으로 바꿔줄 수 있다.

 

Product.kt

package com.android.applemarket

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class Product (
    var pnum :Int , //번호
    var imgsrc : Int , //이미지 파일명
    var pname : String , //상품명
    var pcontent : String ,  //상품 소개
    var seller : String , //판매자
    var price : Int , //가격
    var address : String, //주소
    var like : Int, //좋아요 수
    var chat : Int //채팅 수
) : Parcelable

리사이클러 뷰어로 불러내기 전에 안에 넣을 내용들을 클래스로 만들었다.

@Parcelize를 이용하여 액티비티 간에 객체를 전달할 수 있도록 하였다.

 

ListAdapter.kt

package com.android.applemarket


class ListAdapter (val Items: MutableList<Product>) : RecyclerView.Adapter<ListAdapter.Holder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding = MainListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.itemView.setOnClickListener {  //클릭이벤트추가부분
            itemClick?.onClick(it, position)
        }

        holder.itemView.setOnLongClickListener {
            //Log.d("test","position: ${holder.adapterPosition}")
            itemClick?.longClick(it,holder.adapterPosition) //구글에서 권장하는 방식 adapterPosition
            true   //롱클릭의 경우 true로 해야 한다. 롱클릭이벤트만 발생한다.
        }
        holder.pname.text = Items[position].pname
        holder.address.text = Items[position].address
        //val imgname = Items[position].imgsrc
        //val resId = resources.getIdentifier(imgname,"drawble","com.android.applemarket")
        holder.imgsrc.setImageResource(Items[position].imgsrc)

        val deciamlFormat = DecimalFormat("#,###")  //숫자 3개마다, 표시
        val cPrice = deciamlFormat.format(Items[position].price)
        holder.price.text = cPrice.toString()

        holder.chat.text = Items[position].chat.toString()
        holder.like.text = Items[position].like.toString()

    }


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

    inner class Holder(val binding: MainListItemBinding) : RecyclerView.ViewHolder(binding.root) {

        var imgsrc = binding.ivItemPic2
        var pname = binding.tvItemTitle
        var price = binding.tvPrice
        var address = binding.tvAddress
        var like =binding.tvLikeCount
        var chat =binding.tvCommentCount
    }

}

 

유의하여 보아야할 건 inner class Holder이다. 아까 위에 main_list_item 에서 아이디를 걸어줬었던 .뷰들을 속성으로 만들어 준다. 매개변수로 있는 binding: MainListItemBinding 은 바인딩된 xml이다. 

 

연결을 했으니 이제 값을 바꿔주자.

onBindViewHolder에서 값을 바꿔줄 수 있다.

 

holder라는 매개변수에는 바인딩된 뷰가 있다. 속성들을 보면 Holder라는 클래스에서 정해줬던 속성들인 것을 확인할 수 있다. 

 

Items는 메인에서 넣어줄 것이다.

 

MainActivity.kt

package com.android.applemarket


class MainActivity : AppCompatActivity() {
  
    val dummyData = mutableListOf<Product>()

        dummyData.add(Product(4,R.drawable.sample4,"금고","금고\n떼서 가져가야함\n대우월드마크센텀\n미국이주관계로 싸게 팝니다","Nicole",10000,"해운대구 우제2동",14,17))
        dummyData.add(Product(5,R.drawable.sample5,"갤럭시Z플립3 팝니다","갤럭시 Z플립3 그린 팝니다\n항시 케이스 씌워서 썻고 필름 한장챙겨드립니다\n화면에 살짝 스크래치난거 말고 크게 이상은없습니다!","절명",150000,"연제구 연산제8동",22,9))
        dummyData.add(Product(6,R.drawable.sample6,"프라다 복조리백","까임 오염없고 상태 깨끗합니다\n정품여부모름","미니멀하게",50000,"수원시 영통구 원천동",25,16))
        dummyData.add(Product(7,R.drawable.sample7,"울산 동해오션뷰 60평 복층 펜트하우스 1일 숙박권 펜션 힐링 숙소 별장","울산 동해바다뷰 60평 복층 펜트하우스 1일 숙박권\n(에어컨이 없기에 낮은 가격으로 변경했으며 8월 초 가장 더운날 다녀가신 분 경우 시원했다고 잘 지내다 가셨습니다)\n1. 인원: 6명 기준입니다. 1인 10,000원 추가요금\n2. 장소: 북구 블루마시티, 32-33층\n3. 취사도구, 침구류, 세면도구, 드라이기 2개, 선풍기 4대 구비\n4. 예약방법: 예약금 50,000원 하시면 저희는 명함을 드리며 입실 오전 잔금 입금하시면 저희는 동.호수를 알려드리며 고객님은 예약자분 신분증 앞면 주민번호 뒷자리 가리시거나 지우시고 문자로 보내주시면 저희는 카드키를 우편함에 놓아 둡니다.\n5. 33층 옥상 야외 테라스 있음, 가스버너 있음\n6. 고기 굽기 가능\n7. 입실 오후 3시, 오전 11시 퇴실, 정리, 정돈 , 밸브 잠금 부탁드립니다.\n8. 층간소음 주의 부탁드립니다.\n9. 방3개, 화장실3개, 비데 3개\n10. 저희 집안이 쓰는 별장입니다.","굿리치",150000,"남구 옥동",142,54))
        dummyData.add(Product(8,R.drawable.sample8,"샤넬 탑핸들 가방","샤넬 트랜디 CC 탑핸들 스몰 램스킨 블랙 금장 플랩백 !\n + \"\n\" + \"색상 : 블랙\n\" + \"사이즈 : 25.5cm * 17.5cm * 8cm\n\" + \"구성 : 본품더스트\n\" + \"n\" + \"급하게 돈이 필요해서 팝니다 ㅠ ㅠ","난쉽",180000,"동래구 온천제2동",31,7))
        dummyData.add(Product(9,R.drawable.sample9,"4행정 엔진분무기 판매합니다.","3년전에 사서 한번 사용하고 그대로 둔 상태입니다. 요즘 사용은 안해봤습니다. 그래서 저렴하게 내 놓습니다. 중고라 반품은 어렵습니다.\n","알뜰한",30000,"원주시 명륜2동",7,28))
        dummyData.add(Product(10,R.drawable.sample10,"셀린느 버킷 가방","22년 신세계 대전 구매입니당\n + \"셀린느 버킷백\n\" + \"구매해서 몇번사용했어요\n\" + \"까짐 스크래치 없습니다.\n\" + \"타지역에서 보내는거라 택배로 진행합니당!\"","똑태현",190000,"중구 동화동",40,6))


        val adapter =  ListAdapter(dummyData) //어뎁터에 데이터를 넣고 선언
        binding.rvMainList.adapter=adapter //리사이클러뷰에 어댑터를 적용해준다.
        binding.rvMainList.layoutManager= LinearLayoutManager(this) //레이아웃 매니저로 형식을 정해준다.
        //가로로 하고 싶으면 아래처럼 하면 된다.
        //binding.rvMainList.layoutManager =LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)  

   
    }


    


}

 

메인에서는 여태 만들었던 어댑터를 레이아웃에 연결만 시켜주면 된다. 

 

728x90
반응형

댓글