관리 메뉴

나만을 위한 블로그

[Android] 데이터바인딩, 리사이클러뷰, 콜백을 사용해 클릭 이벤트 구현하기 본문

Android

[Android] 데이터바인딩, 리사이클러뷰, 콜백을 사용해 클릭 이벤트 구현하기

참깨빵위에참깨빵_ 2022. 7. 18. 22:47
728x90
반응형

리사이클러뷰의 아이템 클릭 이벤트는 예전에 작성했던 리사이클러뷰 클릭 이벤트 포스팅으로도 구현할 수 있지만 이렇게도 구현할 수 있어서 포스팅한다. 각자 상황에 맞는 방법으로 구현하는 게 좋겠다.

 

https://onlyfor-me-blog.tistory.com/40

 

[Android] 리사이클러뷰 클릭 이벤트 2

참고한 사이트 : https://recipes4dev.tistory.com/168 리사이클러뷰에서도 리스트뷰처럼 setOnItemClickListener() 사용과 유사한 방법을 통해 아이템 클릭 이벤트를 처리할 수 있나? 디벨로퍼에는 이와 같은 or..

onlyfor-me-blog.tistory.com

 

제목에 적은 대로 이 포스팅에서 사용할 것은 3가지다.

 

  • 데이터바인딩
  • 리사이클러뷰
  • 콜백 인터페이스

 

먼저 인터페이스를 정의한다. 이 포스팅에선 별도의 인터페이스 파일로 뺐지만 어댑터 안에 내부 인터페이스로 생성해도 상관없다.

 

interface OnSendStateInterface {
    fun sendValue(value: String, position: Int)
}

 

그리고 데이터 바인딩에 사용할 DTO 클래스를 대충 만들어준다.

 

data class Person(
    val name: String,
    val age: String
)

 

아이템의 XML도 아래처럼 대충 만들어준다.

 

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

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".callback.CallbackFirstActivity">

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

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

역시 어댑터도 대충 만들어준다.

 

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.kotlinprac.databinding.ItemPersonBinding

class PersonAdapter(
    private val context: Context,
    private val list: ArrayList<Person>
): RecyclerView.Adapter<PersonAdapter.PersonViewHolder>() {

    private lateinit var binding: ItemPersonBinding
    private var listener: OnSendStateInterface? = null

    inner class PersonViewHolder(binding: ItemPersonBinding): RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Person) {
            binding.model = item

            binding.tvPersonName.setOnClickListener {
                val pos = adapterPosition
                if (pos != RecyclerView.NO_POSITION) {
                    if (listener == null) return@setOnClickListener
                    listener?.sendValue(item.age, pos)
                }
            }
        }
    }

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

    override fun onBindViewHolder(holder: PersonViewHolder, position: Int) {
        val item = list[position]
        holder.bind(item)
    }

    override fun getItemCount(): Int = list.size

    fun setOnStateInterface(listener: OnSendStateInterface) {
        this.listener = listener
    }
}

 

전역 변수로 위에서 만든 인터페이스의 참조변수를 null로 만들고 setOnStateInterface()로 이 인터페이스의 참조변수를 받아서 어댑터 안의 listener 참조변수에 넣는다. 이 setOnStateInterface()는 액티비티에서 호출할 것이기 때문에 리사이클러뷰를 초기화할 때 인터페이스 안의 추상 함수는 이 때 같이 초기화된다.

마지막으로 액티비티 코드다.

 

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.kotlinprac.databinding.ActivityCallbackFirstBinding

class CallbackFirstActivity : AppCompatActivity() {

    private val TAG = this.javaClass.simpleName
    private val binding by lazy {
        ActivityCallbackFirstBinding.inflate(layoutInflater)
    }
    private lateinit var personAdapter: PersonAdapter

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

        val list = arrayListOf(
            Person("test1", "1"),
            Person("test2", "2"),
            Person("test3", "3"),
            Person("test4", "4"),
            Person("test5", "5"),
            Person("test6", "6"),
            Person("test7", "7"),
            Person("test8", "8"),
            Person("test9", "9"),
            Person("test10", "10"),
            Person("test11", "11"),
            Person("test12", "12"),
        )
        
        personAdapter = PersonAdapter(this@CallbackFirstActivity, list).apply {
            setOnStateInterface(object : OnSendStateInterface {
                override fun sendValue(value: String, position: Int) {
                    Log.e(TAG, "콜백으로 받은 값 : $value, position : $position")
                }
            })
        }

        binding.run {
            rvPerson.apply {
                layoutManager = LinearLayoutManager(this@CallbackFirstActivity)
                setHasFixedSize(true)
                adapter = personAdapter
            }
        }
    }

}

 

대충 리스트를 만들고 어댑터를 초기화한 다음 리사이클러뷰에 붙인다.

이렇게 하고 앱을 빌드해서 test1, test2 등을 클릭해보면 로그가 이렇게 출력되는 걸 볼 수 있다.

 

반응형
Comments