안드로이드 코틀린 : RecyclerView Item 버튼 이벤트 추가 하기(with ViewBinding)
Lucy Archive
Lucy / Facilitate4U
2021. 4. 10. 15:56

Android Kotlin : RecyclerView Item Button Listener(with ViewBinding)

지난 포스트에서 RecyclerView 를 사용하여 심플한 목록을 만드는 법에 대해 작성하였습니다. 이번 포스트는

RecyclerView의 목록에 버튼을 추가하여 버튼 이벤트를 추가하는 간단한 예제

입니다. RecyclerView에 클릭 이벤트를 만드는 방법은 여러가지가 있지만, 이번 포스트에서는 버튼(또는 뷰) 클릭시 MainActivity의 메서드를 호출 하는 방법을 사용하였습니다. 지난 RecyclerView관련 포스트는 아래를 참고해주세요.

RecyclerView로 목록 만들기

 

안드로이드 코틀린 : RecyclerView로 목록 만들기(with ViewBinding)

Android Kotlin : RecyclerView로 목록 만들기 with ViewBinding Android Studio 의 Kotlin 언어에서 ViewBinding를 사용하여 RecylerView로 목록을 만드는 예제 입니다. RecyclerView가 처음이면 간단하게 목록..

juahnpop.tistory.com

 

프로젝트 생성 및 환경 설정

아래의 버튼 기능을 가진 RecyclerView 예제입니다. 하단의 실행 결과를 먼저 참고하시면 됩니다. 

  • Button1 : 해당 목록 삭제
  • Button2 : 해당 목록의 텍스트 수정

프로젝트 생성

아래 그림과 같이 프로젝트를 생성합니다.

  • 프로젝트명 : RecyclerView
  • 사용언어 : Kotlin

※ 이 포스트는 Android Studio 4.1.2, Kotlin 1.4.31 버전으로 작성하였습니다.

 

ViewBinding 설정

App > Gradle Scripts > build.gradle 에 ViewBinding 설정을 위해 아래의 코드를 추가합니다. 코드 추가가 완료되면 Sync Now 를 클랫해서 Gradle 변경 사항을 적용합니다.

android { 
	... 
    viewBinding { 
    	enabled = true 
    } 
}

Gragle 수정 사항 적용

※ ViewBinding은 Layout에 있는 View의 Id를 코틀린 코드에서 사용 할 수 있도록 해주는 도구입니다. View Binding과 관련된 설명은 아래의 링크를 참조해주세요.

안드로이드 View Binding 사용하기

 

안드로이드 View Binding 사용하기 - kotlin-android-extensions 지원 중단

안드로이드 View Binding 방법 정리 안드로이드 코드에서 레이아웃 View에 접근하기 위해 사용된 kotlin-android-extensions 의 지원이 중단예정으로, 이를 대체하여 사용 할 수 있는 ViewBinding 사용법에 대해

juahnpop.tistory.com

 

레이아웃 UI 작성

activity_main.xml 코드 작성

아래와 같이 activity_main.xml 레이아웃 파일에 RecyclerView와 FAB(FloatingActionButton)을 추가합니다. 아래와 같이 코드를 작성한 UI 화면은 코드 아래 그림과 같습니다. 

<?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=".MainActivity">

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

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:contentDescription="NewProject"
        android:src="@android:drawable/ic_input_add"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml

item_recycler.xml 레이아웃 작성

RecyclerView의 Item레이아웃을 작성하기 위해 아래 그림과 같이 item_recycler.xml 리소스 파일을 추가 후 아래와 같이 TextView 하나와 Button2개를 추가합니다.

item_recycler.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"
    android:layout_width="match_parent"
    android:layout_height="50dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:gravity="center"
        app:layout_constraintEnd_toStartOf="@+id/btnDelete"
        app:layout_constraintStart_toEndOf="@+id/btnEdit" />

    <Button
        android:id="@+id/btnEdit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Edit"
        android:layout_marginStart="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Del"
        android:layout_marginEnd="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

item_recyler.xml 의 레이아웃

 

alertdialog_edittext.xml 레이아웃 작성

위의 레이아웃 추가 방법과 동일하게 alertdialog_edittext.xml 리소스 파일을 추가하여 아래와 같이 코드를 입력합니다. 이 레이아웃은 EditText를 포함한 AlertDialog를 추가하기 위해 사용됩니다. item_recycler.xml 의 Edit버튼을 누르고 변경할 텍스트를 입력받기 위한 용도로 사용합니다.

<?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">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="22dp"
        android:layout_marginEnd="22dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

※ EditText가 포함된 AlertDialog를 사용하는 방법은 아래 링크를 참고해주세요.

AlertDialog : 기본, 목록, 라디오 버튼, 체크 박스, EditText 입력창

 

안드로이드 코틀린 : AlertDialog 기본, 목록, 라디오 버튼, 체크 박스, EditText 입력 창

안드로이드 코틀린 : AlertDialog 기본, 목록, 체크박스 목록, 라디오 버튼 목록, 입력(Edit Text) 사용법 이번 포스트는 안드로이드 코틀린 언어를 사용하여 AlertDialog를 활용한 기본 사용 방법, 목록 선

juahnpop.tistory.com

 

코틀린 코드 작성

RecyclerView Item에 맞는 Data Class 생성

RecyclerView Item 레이아웃에 맞는 Data Class를 생성합니다. 클래스 이름은 Member으로 합니다.

Member Class 파일 생성

Member 데이터 클래스를 아래와 같이 생성합니다. 코틀린에서 data class는 class앞에 data 선언문을 이용해 생성합니다. 클래스의 사용에 따라 클래스 멤버(프로퍼티)가 변경될 수 있는 경우 val이 아닌 var로 선언하면 됩니다.

package com.blacklog.recyclerview

data class Member(val name: String)

 

RecyclerView 아답터 클래스 생성

아래와 같이 MyAdapter클래스 파일을 생성합니다.

RecyclerView Adapter로 사용할 MyAdapter 클래스 생성

MyAdapter.kt 파일에 아래와 같이 코드를 작성합니다. MyAdapter 클래스 내의 onCreatViewHolder, onBindViewHolder, getItemCount 메서드는 RecyclerView.Adapter 인터페이스의 구성원으로 Ctrl+I 를 눌러오버라이드 합니다. 

  • onCreateViewHolder : 어떤 목록 레이아웃(껍데기)을 만들 것인지 반환(어떤 뷰를 생성 할 것인가)
  • onBindViewHolder : 생성된 뷰(껍데기)에 무슨 데이터를 넣을 것인가
  • getItemCount() : 몇 개의 목록을 만들지를 반환
  • Holder클래스(ViewHolder) : 목록의 개별 항목 레이아웃을 포함하는 View 래퍼로, 각 목록 레이아웃에 필요한 기능들을 구현 하는 공간. ex) 아이템 레이아웃에 버튼이 있는 경우 버튼 리스너는 Holder 클래스에서 구현
package com.blacklog.recyclerview

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.blacklog.recyclerview.databinding.ItemRecyclerBinding

class MyAdapter : RecyclerView.Adapter<Holder>(){

    var listData = mutableListOf<Member>()

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

    override fun onBindViewHolder(holder: Holder, position: Int) {
        val member = listData[position]
        holder.setData(member, position)
    }

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

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

    private val mainActivity = MainActivity.getInstance()
    var mMember: Member? = null
    var mPosition: Int? = null

    init {
        binding.btnDelete.setOnClickListener {
            mainActivity?.deleteMember(mMember!!)
        }

        binding.btnEdit.setOnClickListener {
            mainActivity?.editMember(mPosition!!, mMember!!)
        }
    }

    fun setData(member: Member, position: Int){
        binding.textView.text = member.name
        this.mMember = member
        this.mPosition = position
    }
}

item_recycler.xml 에 있는 버튼의 Click 이벤트는 Holder 클래스 내의 init 부분에 작성하였습니다. 목록 아이템이 10개 생성되는 경우 목록의 갯수만큼 Holder 클래스 객체가 따로따로 존재한다고 생각하시면 됩니다. 

  • id : btnDelete 버튼 👉 MainActivity의 deleteMember() 메서드를 실행
  • id : btnEdit 버튼 👉 MainActivity의 editMember() 메서드를 실행

Holder 클래스와 같이 일반 클래스에서 MainActivity의 메서드를 실행하는 방법은 아래의 링크를 참고해주세요. 

일반 클래스에서 MainActivity의 메서드 사용하기

 

안드로이드 코틀린 : 일반 클래스 또는 Fragment에서 MainActivity의 메서드 사용하기

Android Kotlin : 일반 Class에서 MainActivity의 프로퍼티 및 메서드 사용하기 일반 Class 와 Fragment에서 MainActivity의 메서드 및 프로퍼티 사용 방법 에 대해 작성하였습니다. Fragment 에서 MainActivity..

juahnpop.tistory.com

 

MainActivity에서 RecyclerView와 MyAdapter연결

앞서 생성한 아답터 클래스와 RecyclerView를 연결하는 코드는 MainActivity.kt 에서 아래와 같이 작성하였습니다. 아래 코드에서는 간단히 코드 내의 data:mutableList<Member> 배열에서 RecyclerView에 연결하였습니다. 리사이클러 아이템뷰의 버튼 클릭시 실행할 메서드도 작성하였습니다. 

  • deleteMember()
    • 선택된 리사이클러뷰 목록의 Member를 data 배열에서 삭제
    • 리사이클러에 데이터 변경을 알림
  • editMember()
    • EditText 알림창으로 변경할 텍스트를 입력 받음
    • 선택된 Member의 Name 값을 변경
    • 수정된 Member를 data 배열에 반영
    • 리사이클러에 데이터 변경을 알림
package com.blacklog.recyclerview

import android.content.DialogInterface
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import com.blacklog.recyclerview.databinding.ActivityMainBinding
import com.blacklog.recyclerview.databinding.AlertdialogEdittextBinding

class MainActivity : AppCompatActivity() {

    // ViewBinding
    private lateinit var binding : ActivityMainBinding

    // RecyclerView 가 불러올 목록
    private var adapter: MyAdapter? = null
    private val data:MutableList<Member> = mutableListOf()
    var i = 4

    init{
        instance = this
    }

    companion object{
        private var instance:MainActivity? = null
        fun getInstance(): MainActivity? {
            return instance
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        // ViewBinding
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        initialize() // data 값 초기화
        adapter = MyAdapter()
        adapter!!.listData = data
        binding.recyclerView.adapter = adapter
        binding.recyclerView.layoutManager = LinearLayoutManager(this)

        // FAB 을 누르면 Member + 숫자의 문자열이 data 배열에 추가됨
        binding.fab.setOnClickListener {
            val string = "Member$i"
            i++
            data.add(Member(string))
            adapter?.notifyDataSetChanged()
        }
    }

    private fun initialize(){
        with(data){
            add(Member("Member1"))
            add(Member("Member2"))
            add(Member("Member3"))
        }
    }

    fun deleteMember(member: Member){
        data.remove(member)
        adapter?.notifyDataSetChanged()
    }

    fun editMember(position: Int, member: Member){

        val builder = AlertDialog.Builder(this)
        val builderItem = AlertdialogEdittextBinding.inflate(layoutInflater)
        val editText = builderItem.editText

        with(builder){
            setTitle("Input Name")
            setMessage("이름을 입력 하세요")
            setView(builderItem.root)
            setPositiveButton("OK"){ _: DialogInterface, _: Int ->
                if(editText.text.toString() != null){
                    member.name = editText.text.toString()
                    data[position] = member
                    adapter?.notifyDataSetChanged()
                }
            }
            show()
        }
    }
}

 

실행 결과

위 코드를 작성 후 실행하면 아래와 같이, 어플 실행시 RecyclerView에 Member1 ~ Member3 목록이 생기고, FAB 버튼을 누르면 Member4 부터 하나씩 데이터가 늘어납니다. DEL 버튼을 누르면 목록이 삭제 되고, EDIT 버튼을 누르면 목록의 텍스트를 수정합니다. 

실행 결과

요약

저는 RecyclerView를 만들기 위해 아래와 같은 순서로 진행하였습니다.

  • 어떤 디자인형태(Item Layout)의 목록을 만들 건지 정하기
  • 디자인형태에 맞는 RecyclerView_Item 레이아웃 코드 작성
  • 디자인 형태에 맞는 Data Class 만들기
  • Custom Recycler Adapter 클래스 만들기
    • View Holder 클래스 만들기
    • View Holder 클래스에 버튼 이벤트 추가하기
  • MainActivity와 연결 하기

끝까지 읽어 주셔서 감사합니다.^^

관련포스트

🤞 안드로이드(코틀린) 앱 제작하기 관련글 목록 보기

🤞 안드로이드(코틀린) 리사이클러뷰 관련글 목록 보기

🤞 안드로이드(코틀린) 목록만들기 관련글 목록 보기