[Android/Kotlin] RecyclerView Divider - 구분선 만들기

Notepad96

·

2022. 8. 27. 22:01

300x250

 

 

1. 요약

 

결과

 

이번 글에서는 RecyclerView에서 각 항목 사이를 구분하기 위해 도와주는 구분선을 삽입하기 위한 방법에 관하여 알아본다.

 

구분선을 삽입하기 위해서는 이미 정의되어 있는 DividerItemDecoreation을 사용할 수 있으며 ItemDecoration을 상속받은 후 오버라이드 즉, 재정의를 해줌으로써 Custom 한 구분선 삽입도 가능하다.

 

 

 

 

2. 레이아웃

 

2-1. activity_main.xml

메인 레이아웃으로서 리스트를 나타낼 RecyclerView 1개로 구성된다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context=".MainActivity">

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

  </LinearLayout>

 

2-2. item_list.xml

리스트의 항목에 레이아웃으로 TextView 2개로 구성하였다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp">

    <TextView
        android:id="@+id/mainText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Main"
        android:textSize="20sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/subText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Sub"
        android:gravity="right"
        android:textSize="18sp" />

</LinearLayout>

 

 

 

 

3. 코드 및 설명

 

3-1. MainActivity.kt

구분선을 삽입하기 위해서는 DividerItemDecoreation을 초기화한 후, addItemDecoreation을 통하여 추가해줌으로써 아래와 같이 이미 정의되어 있는 구분선이 삽입된다.

 

간단하게 구분선을 추가하기 위해서 유용하게 사용이 가능하다.

 

단, 결과를 확인해보면 마지막 항목의 아래쪽에도 구분선이 삽입되는 것을 볼 수 있으며 이를 제거하기 위해서는 아래 CustomItemDecoreation처럼 재정의를 해줌으로써 해결 가능하다.

 

DividerItemDecoration

 

package com.notepad96.recyclerviewdivider

import android.os.Bundle
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.notepad96.recyclerviewdivider.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        binding.recycler01.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = ListAdapter()
            setHasFixedSize(true)
            // 1. 정의되어 있는 구분선
            addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL))
            // 2. Custom 구분선
//            addItemDecoration(CustomItemDecoration())

        }
    }
}

 


 

3-2. CustomItemDecoreation.kt

구분선을 다른 스타일로 그리기 위해서 c.drawRect를 통하여 사각형을 그려주도록 한다.

 

drawRect의 인수는 (left, top, right, bottom, paint) 로서 사각형을 그리는 방법은 좌표 (left, top)과 (right, bottom)을 연결하면 대각선의 선이 된다. 그러면 이를 대각선으로 가지는 사각형이 그려지게 되는 것이다.

 

따라서 left, top, right, bottom 각 값들을 이에 맞도록 초기화해주어야 하며, left를 보면 parent.paddingLeft로 부모 레이아웃에 Left Padding으로 초기화해준다. 이처럼 나머지 값들도 Padding과 Margin을 고려해서 초기화해주면 된다.

 

 

추가적으로 widthMargin과 height을 정의하여 widthMargin값만큼 좌우의 Margin을 부여하며, height만큼의 높이를 갖는 사각형이 구분선으로 삽입되게 된다.

 

 

CustomItemDecoration

 

package com.notepad96.recyclerviewdivider

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import androidx.recyclerview.widget.RecyclerView

class CustomItemDecoration(): RecyclerView.ItemDecoration() {
    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
        val widthMargin = 20f   // 좌우 Margin
        val height = 5f         // 사각형의 height

        val left = parent.paddingLeft.toFloat()
        val right = parent.width - parent.paddingRight.toFloat()
        val paint = Paint().apply { color = Color.RED }
        for(i in 0 until parent.childCount) {
            val view = parent.getChildAt(i)
            val top = view.bottom.toFloat() + (view.layoutParams as RecyclerView.LayoutParams).bottomMargin
            val bottom = top + height   // 세로 길이 = 5 (bottom - top = height)

            // 좌표 (left, top) / (right, bottom) 값을 대각선으로 가지는 사각형
            c.drawRect(left + widthMargin, top, right - widthMargin, bottom, paint)
        }
    }
}

 

 

 

 

4. 전체 파일

 

 

GitHub - Notepad96/BlogExample02

Contribute to Notepad96/BlogExample02 development by creating an account on GitHub.

github.com

 

 

 

300x250