경험의 기록

RecyclerView 는 안드로이드 개발을 할 때 자주 사용하게 된다.

그런데 만들때마다 조금씩 헷갈릴 때가 있어서, 하나하나 깔끔하게 과정을 정리하여 참고할 수 있는 라이브러리처럼 만들어 보고자 한다.

 

또한 RecyclerView 에 ViewBinding 을 사용해보고자 한다.

 


사용해보기

리싸이클러뷰 아이템 만들기

일단 메인액티비티 레이아웃에 리싸이클러뷰를 추가해주고,

 

리싸이클러뷰에 표현될 아이템 형식을 지정할 레이아웃을 추가해준다.

 

<?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="wrap_content"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <TextView
                android:id="@+id/name_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginTop="16dp"
                android:text="TextView"
                android:textSize="30sp"
                android:textStyle="bold"
                app:layout_constraintStart_toEndOf="@+id/imageView"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/description_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textSize="16sp"
                app:layout_constraintStart_toStartOf="@+id/name_text"
                app:layout_constraintTop_toBottomOf="@+id/name_text" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</LinearLayout>

다음과 같이 이미지 하나와 제목, 설명이 들어가는 아이템 뷰를 작성하였다.

 

뷰바인딩 추가

    // 익스텐션 대신 뷰바인딩
    buildFeatures {
        viewBinding true
    }

bulid.gradle 의 android 에 추가해준다.

 

 

넣을 임의의 값 지정

<resources>
    <string name="app_name">RecyclerViewEx</string>

    <string-array name="item_name">
        <item>Item 1</item>
        <item>Item 2</item>
        <item>Item 3</item>
        <item>Item 4</item>
        <item>Item 5</item>
        <item>Item 6</item>
        <item>Item 7</item>
        <item>Item 8</item>
    </string-array>

    <string-array name="item_description">
        <item>Item 1 입니다.</item>
        <item>Item 2 입니다.</item>
        <item>Item 3 입니다.</item>
        <item>Item 4 입니다.</item>
        <item>Item 5 입니다.</item>
        <item>Item 6 입니다.</item>
        <item>Item 7 입니다.</item>
        <item>Item 8 입니다.</item>
    </string-array>
</resources>

valuesstrings 에 임의의 제목, 설명을 8가지 지정해주었다.

 

 

리싸이클러뷰 어댑터 생성

class MyAdapter(val nameList : Array<String>, val desList : Array<String>)
    : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    // 생성된 뷰 홀더에 값 지정
    class MyViewHolder(val binding: RecyclerviewItemBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(name: String, des: String) {
            // 뷰 홀더의 제목과 설명
            binding.nameText.text = name
            binding.descriptionText.text = des

            // 뷰 홀더 클릭시 디테일뷰로
            binding.cardView.setOnClickListener {
                val intent: Intent = Intent(it.context, DetailViewActivity::class.java)
                intent.putExtra("currentName", name)
                intent.putExtra("currentDes", des)
                it.context.startActivity(intent)
            }
        }
    }

    // 어떤 xml 으로 뷰 홀더를 생성할지 지정
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = RecyclerviewItemBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return MyViewHolder(binding)
    }

    // 뷰 홀더에 데이터 바인딩
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bind(nameList[position],desList[position])
    }

    // 뷰 홀더의 개수 리턴
   override fun getItemCount(): Int {
        return nameList.size
    }
}

리싸이클러뷰에 연결해줄 어댑터를 생성한다.

 

하나씩 살펴보면

리싸이클러뷰 어댑터를 상속받는다.

파라미터로는 제목 리스트와 설명 리스트를 받도록 한다.

 

상속받은 어댑터에서 3개의 메소드를 구현해야하는데,

onCreateViewHolder 는 어떤 xml로 뷰 홀더를 생성할지 지정해주는 메소드이다.

여기서 뷰 바인딩을 사용하여 바인딩한다.

 

onBindViewHolder 는 뷰 홀더에 데이터를 바인딩 해주는 부분이며 커스텀해준 뷰 홀더의 메소드를 호출할 것이다.

 

getItemCount 는 뷰 홀더의 개수를 리턴해주는 메소드로 인자로 사용한 갯수를 리턴해주면 된다.

 

여기서 파라미터로 바인딩을 받아주며 뷰홀더에서 바인딩한 부분의 root 를 상속받아 뷰를 만든다.

bind 메소드를 작성하여 뷰 홀더마다 제목과 설명을 할당해주고, 뷰 홀더를 클릭 시 인텐트를 생성하여 Extra 값을 넘겨줘 그 값을 받아 출력하는 별도의 창이 뜨도록 할 것이다.

어댑터에서 인텐트의 context(it.context)binding.cardView.context 이다.

 

디테일뷰 만들기

<?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="match_parent"
    tools:context=".DetailViewActivity">

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="170dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="93dp"
        android:text="TextView"
        android:textSize="32sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView2" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="62dp"
        android:text="TextView"
        android:textSize="16sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>

액티비티를 하나 만들어서, 여기에 뷰 홀더에 따른 제목과 설명을 출력할 것이다.

class DetailViewActivity : AppCompatActivity() {

    private lateinit var binding: ActivityDetailViewBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 뷰 바인딩
        binding = ActivityDetailViewBinding.inflate(layoutInflater)
        setContentView(binding.root)

        getData()
    }

    // 클릭된 뷰에 관한 데이터를 보여줌
    fun getData(){
        if(intent.hasExtra("currentName") && intent.hasExtra("currentDes")){
            binding.textView.text = intent.getStringExtra("currentName")
            binding.textView2.text = intent.getStringExtra("currentDes")
        }
        else{
            Toast.makeText(this,"불러오기 실패",Toast.LENGTH_SHORT).show()
        }
    }

}

뷰 바인딩을 해주고

뷰 홀더에서 넘겨준 Extra 값을 받아와 텍스트에 할당해준다.

 

메인액티비티

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    lateinit var nameList : Array<String>
    lateinit var descriptionList : Array<String>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 뷰 바인딩
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 이름과 설명 초기화
        nameList = resources.getStringArray(R.array.item_name)
        descriptionList = resources.getStringArray(R.array.item_description)

        // 아이템을 가로로 하나씩 보여줌
        binding.recyclerView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)

        // 어댑터 연결
        binding.recyclerView.adapter = MyAdapter(nameList,descriptionList)

    }
}

처음에 작성한 리스트들을 할당하여 어댑터에 연결해준다.

 

 

잘 구현 되었다.

 

https://github.com/HanYeop/AndroidStudio-Practice/tree/master/RecyclerViewEx

 

HanYeop/AndroidStudio-Practice

안드로이드 학습 내용 저장소. Contribute to HanYeop/AndroidStudio-Practice development by creating an account on GitHub.

github.com

 

 

 

 

 

참조

https://www.youtube.com/watch?v=18VcnYN5_LM

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading