안드로이드

[Android] RecyclerView GridLayoutManager 헤더, 푸터, spanSizeLookup 작업

코딩하는후운 2024. 5. 10. 14:39
반응형

RecyclerView GridLayoutManager 헤더, 푸터, spanSizeLookup 작업

작업중에

헤더 푸터는 전체 칼럼으로 보여줘야하고, 그리드 영역은 span size 에 맞게 처리 해야하는 작업이 필요했습니다.
아래 표와 같은 형태

헤더
그리드 영역  
   
푸터

 

1. RecyclerView에 GridLayoutManager 설정

val layoutManager = GridLayoutManager(context, 2) // 전체 칼럼 수를 2으로 설정
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
    override fun getSpanSize(position: Int): Int {
        return when (adapter.getItemViewType(position)) {
            Adapter.TYPE_HEADER,
            Adapter.TYPE_FOOTER -> 2 // 헤더와 푸터는 2칼럼 차지
            else -> 1 // 나머지 아이템은 1칼럼 차지
        }
    }
}


recyclerView.layoutManager = layoutManager
recyclerView.addItemDecoration(
    Adapter.GridSpacingItemDecoration(
        2,
        dp2px(12)
    )
)
recyclerView.adapter = adapter

 

2. 위에 소스에서 addItemDecoration을 해주었는데, 나는 각 아이템간의 여백을 주고 싶어서 GridSpacingItemDecoration을 적용 하였습니다.

- 헤더, 푸터는 여백 없음.
- 각 그리드 아이템들 간에는 여백을 주고 싶었다.

/**
 * 그리드 아이템 사이 여백을 주기 위한 ItemDecoration
 */
class GridSpacingItemDecoration(
    private val spanCount: Int,
    private val spacing: Int
) : RecyclerView.ItemDecoration() {

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val position = parent.getChildAdapterPosition(view)
        val viewType = parent.adapter?.getItemViewType(position)

        if (viewType == TYPE_ITEM) {
            val column = (position - HEADER_COUNT) % spanCount // 현재 칼럼 위치

            outRect.left = column * spacing / spanCount
            outRect.right = spacing - (column + 1) * spacing / spanCount

            if (position - HEADER_COUNT >= spanCount) { // 0,1,2 = 0 여백, 3부터 상단 여백
                outRect.top = spacing
            }
        } else {
            // 헤더나 푸터인 경우 여백 없음
            outRect.setEmpty()
        }
    }
}

 

그 다음은 일반 리싸이클러뷰 GridLayoutManager와 동일하게 적용 하면 된다.

알게 된 점

1. GridLayoutManager.SpanSizeLookup에서는 getSpanSize() 메서드가 호출되므로 독점하고 싶은 열의 개수를 반환한다. 

2. addItemDecoration을 통해 각 그리드 사이의 여백을 적용 할 수 있음.

 

반응형