본문 바로가기
안드로이드 코틀린

[Kotlin][Android] 리사이클러뷰 아이템 스와이프 구현하기

by teamnova 2021. 10. 19.

안녕하세요!

이번 포스팅에서는 아래와 같이 리사이클러뷰의 아이템을 스와이프했을 때의 동작을 구현해보겠습니다.

 

 

 

 

 

리사이클러뷰 아이템을 클릭했을 때의 동작을 정의하는 ItemTouchHelper.Callback 클래스를 커스텀하여 구현하는 방법도 있지만, 이번 포스팅에서는 github에 있는 스와이프 레이아웃 오픈소스를 사용해보겠습니다.

 

 

오픈소스를 사용하기 위해 앱수준 gradle에 다음과 같이 추가해줍니다.

dependencies {
    ...

//    스와이프
    implementation 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.1'
}

 

구현의 핵심이 되는 리사이클러뷰의 아이템 레이아웃을 만듭니다.

item_swipe2.xml

이미지뷰에 사용한 이미지는 Resource Manager를 통해 간편하게 원하는 것을 추가해 설정하시면 됩니다.

<?xml version="1.0" encoding="utf-8"?>
<com.chauthai.swipereveallayout.SwipeRevealLayout 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="70dp"
    app:dragEdge="left"
    app:mode="normal">

    <!--스와이프 레이아웃-->
    <LinearLayout
        android:id="@+id/ly_swipe"
        android:layout_width="130dp"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_share"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/teal_200"
            android:paddingHorizontal="20dp"
            android:src="@drawable/ic_baseline_send_24" />

        <ImageView
            android:id="@+id/iv_edit"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@color/purple_200"
            android:paddingHorizontal="20dp"
            android:src="@drawable/ic_baseline_edit_24" />

    </LinearLayout>

    <!--메인 레이아웃-->
    <LinearLayout
        android:id="@+id/ly_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:paddingHorizontal="20dp"
        android:background="@color/white"
        android:paddingVertical="10dp"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="item"
            android:textColor="@color/black"
            android:paddingEnd="10dp"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="name"
            android:textColor="@color/black"
            android:textSize="20sp" />

    </LinearLayout>
</com.chauthai.swipereveallayout.SwipeRevealLayout>

스틱코드로 레이아웃 코드를 빠르게 추가하실 수 있습니다.

[AOS][Kotlin] 리사이클러뷰 아이템 스와이프 동작 구현하기 - Stickode

 

 

액티비티 레이아웃에는 간단하게 리사이클러뷰만 추가해주겠습니다.

activity_swipe.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="match_parent"
    tools:context=".activity.SwipeActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

액티비티와 리사이클러뷰 어댑터를 구현해주겠습니다.

뷰를 가져올 때에는 view binding을 사용하였습니다. findViewById로 구현하셔도 무방합니다.

 

Swipe2Activity.kt

class Swipe2Activity : AppCompatActivity() {
    private val binding: ActivitySwipeBinding by lazy {
        ActivitySwipeBinding.inflate(
            layoutInflater
        )
    }

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

        val adapter = Swipe2Adapter(
            object : Swipe2Adapter.OnClickListener {
                override fun onClick(binding: ItemSwipe2Binding, type: SwipeButton) {
                    when (type) {
                        SwipeButton.SHARE -> {
                            showToast("공유 버튼 클릭")
                        }
                        SwipeButton.EDIT -> {
                            showToast("수정 버튼 클릭")
                        }
                    }
                }
            }
        )

        binding.rv.apply {
            layoutManager = LinearLayoutManager(context)
            this.adapter = adapter
        }
    }

    fun showToast(message: String) {
        Toast.makeText(applicationContext, message, Toast.LENGTH_LONG).show()
    }
}

 

Swipe2Adapter.kt

class Swipe2Adapter(private val listener: OnClickListener) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private var items = ArrayList<String>().apply {
        for (i in 1..15)
            add("$i")
    }

    inner class ViewHolder(
        private val binding: ItemSwipe2Binding,
        private val listener: OnClickListener
    ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {

        fun bind(item: String) {
            with(binding) {
                tv.text = item

                ivEdit.setOnClickListener(this@ViewHolder)
                ivShare.setOnClickListener(this@ViewHolder)
            }
        }

        override fun onClick(v: View?) {
            with(binding) {
                when (v) {
                    ivEdit -> listener.onClick(this, SwipeButton.EDIT)
                    ivShare -> listener.onClick(this, SwipeButton.SHARE)
                    else -> Log.d("@@TAG@@", "onClick: swipe viewHolder onclick else view")
                }
            }
        }
    }

    interface OnClickListener {
        fun onClick(binding: ItemSwipe2Binding, type: SwipeButton)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
        ViewHolder(
            ItemSwipe2Binding.inflate(LayoutInflater.from(parent.context), parent, false),
            listener
        )


    override fun getItemCount(): Int {
        return if (items.isNullOrEmpty()) 0 else items.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is ViewHolder)
            holder.bind(items[position])
    }

}