[Android] RecyclerView에 DataBinding 적용하기

27914 단어 androidandroid

만들 화면! 태그들을 RecyclerView로 만들고 DataBinding을 곁들여서 Drawable 이미지와 텍스트를 변경해줄 것이다.

파일 구조는 위와 같다.

🔸 TagData.kt

data class TagData(val tagImage: Drawable, val tagText: String) {
}

RecyclerView에 들어가는 정보인 이미지와 텍스트를 클래스로 정의해준다. 이미지를 url로 받아오는 것이 아니라 drawable에 있는 이미지를 가져올 것이므로 Gilde를 사용하지 않는다.


🔸 tag_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="tag"
            type="com.example.cagong.data.TagData" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/tag_background"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:background="@drawable/rounded_tag"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <ImageView
                android:id="@+id/tag_image"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:src="@{tag.tagImage}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>

        <TextView
            android:id="@+id/tag_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="@{tag.tagText}"
            android:textColor="@color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tag_background" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

TagData에서 데이터를 받아와서 xml에 뿌려줄 것이므로 data영역에 변수 tag를 지정한다. 그리고 데이터바인딩으로 속성을 아래와 같이 정의해준다.

  • ImageView에는 android:src="@{tag.tagImage}"
  • TextView에는 android:text="@{tag.tagText}"

🔸 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <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/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="20dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

메인액티비티에 RecyclerView를 추가한다.


🔸 MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var manager: RecyclerView.LayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        manager = GridLayoutManager(this, 3)

        var data = listOf(TagData(getDrawable(R.drawable.icon_plugin)!!, "콘센트가 많아요"),
            TagData(getDrawable(R.drawable.icon_mute)!!, "조용해요"),
            TagData(getDrawable(R.drawable.icon_table)!!, "책상이 넓어요"),
            TagData(getDrawable(R.drawable.icon_eyes)!!, "눈치가 덜 보여요"),
            TagData(getDrawable(R.drawable.icon_chair)!!, "자리가 편해요"),
            TagData(getDrawable(R.drawable.icon_light)!!, "눈이 편해요")
        )

        binding.recyclerView.apply{
            adapter = TagRecyclerAdapter(data)
            layoutManager = manager
        }
    }
}

TagData의 리스트를 만들어 어댑터에 넘겨준다.

Drawable을 얻어오는 방식

  • getDrawable(R.drawable.리소스명)
  • 뒤에 !!을 붙이지 않으면 넘겨줘야 하는 타입은 Drawable인데 Drawable?을 넘겨줬다는 의미로 타입 미스매치가 발생한다.

🔸 TagRecyclerAdapter.kt

class TagRecyclerAdapter(private val itemList: List<TagData>): RecyclerView.Adapter<TagRecyclerAdapter.MyViewHolder>(){

    inner class MyViewHolder(val binding: TagItemBinding): RecyclerView.ViewHolder(binding.root) {
        fun bind(item: TagData) {
            binding.tag = item
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val listItemBinding = TagItemBinding.inflate(inflater, parent, false)
        return MyViewHolder(listItemBinding)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bind(itemList[position])
    }

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

뷰 객체를 그려주는 ViewHolder, Data와 View를 연결해주는 Adapter를 만들자. 다만 Adapter 클래스 안에 ViewHolder를 넣어줄 것이다.

  • ViewHolder
    : 각각의 뷰를 보관하는 Holder 객체. Item 뷰들을 재활용하기 위해 각 요소를 저장해두고 사용한다. bind 함수는 ViewHolder와 클래스의 각 변수를 연동하는 역할을 한다. 쉽게 말해 '이쪽 TextView엔 이 String을 넣어라'라고 지정하는 함수이다.
  • onCreateViewHolder
    : 화면을 최초 로딩한 상태라 만들어진 View가 없는 경우, xml파일을 inflate하여 ViewHolder를 생성한다.
  • onBindViewHolder
    : bind함수를 통해 위의 onCreateViewHolder에서 만든 View와 실제 입력되는 각각의 데이터를 연결한다.
  • getItemCount
    : RecyclerView로 만들어지는 item의 총 개수를 반환한다.

좋은 웹페이지 즐겨찾기