티스토리 뷰

2022.04.01 - [Android] - Android RecyclerView - ConcatAdapter

ConcatAdapter

ConcatAdapter를 통해 하나의 RecyclerView에서 쉽게 여러 ViewType을 추가할 수 있습니다. 하지만 LayoutManager는 Adapter에 붙는게 아닌 RecyclerView에 붙기 때문에 하나의 LayoutManager만 사용할 수 있다는 단점이 있습니다.

 

만약 요구사항이 아래와 같다면?


NestedScrollView

ScrollView에 Horizontal부분과 Grid부분을 추가하고, Grid 영역 RecyclerView의 height를 wrap_content로 설정하면 해결할 수 있습니다. 하지만 ListView, RecyclerView같은 리스트 형식의 뷰는 크기가 정해지지 않으면 가지고 있는 Item만큼 높이를 차지하고, 한번에 표시하기 때문에 메모리 문제가 생길 수 있습니다.

 

 CoordinatorLayout

Behavior를 구현하기 까다롭고, 스크롤이 부자연스러운 이슈가 생길 수 있습니다. 만약 Linear - Grid - Linear - Grid... 같이 복잡한 레이아웃인 경우 더욱 구현하기 어렵습니다.

 

ConcatAdapter, NestedRecyclerView

ConcatAdapter를 사용하여, 중첩된 RecyclerView를 사용한다면 해당 Layout을 구현할 수는 있습니다. 하지만 여전시 크기 지정 문제가 생기고 RecyclerView를 중첩으로 사용하면서 Scroll이 겹치고, RecyclerView에 RecyclerView를 추가하는 이상한 구조가 됩니다.


ConcatAdapter, GridLayout

GridLayoutManager를 사용하고, viewType마다 spanSize를 설정하면 쉽게 만들 수 있습니다.

 

    private val concatAdapter = ConcatAdapter(
        ConcatAdapter.Config.Builder().apply {
            setIsolateViewTypes(false)
        }.build(),
        getHorizontalSectionAdapter(),
        getGridHeaderAdapter(),
        getStringAdapter()
    )

ConcatAdapter를 만들어줍니다. 이때 주의할 점은 ConcatAdapter가 viewType을 사용하기 위해, Config를 설정합니다. 이때 주의할 점은 ConcatAdapter에 사용되는 Adapter는 ViewType을 올바르게 정의해야 합니다.

 

    private fun initRecyclerView() {
        binding.recyclerView.apply {
            adapter = concatAdapter
        }

        binding.recyclerView.layoutManager = GridLayoutManager(this, 3).apply {
            spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int {
                    return when(concatAdapter.getItemViewType(position)) {
                        R.layout.item_horizontal_section, R.layout.item_grid_header -> 3
                        else -> 1
                    }
                }
            }
        }
    }

RecyclerView의 LayoutManager를 GridLayoutManager로 설정합니다. spanSizeLookup을 재정의하여 viewType마다 spanSize를 설정합니다. 올바르게 작동하기 위해, ConcatAdapter의 Config를 설정하고, Adapter들은 getItemViewType를 올바르게 정의해야 합니다.

 

class HorizontalSectionAdapter : ListAdapter<MainSection.HorizontalSection, HorizontalSectionViewHolder>(DiffCallback()) {
    ...

    override fun getItemViewType(position: Int): Int {
        return R.layout.item_horizontal_section
    }

    ...
}

class GridHeaderAdapter : ListAdapter<Unit, GridHeaderAdapter.GridHeaderViewHolder>(DiffCallback()) {
    ...

    override fun getItemViewType(position: Int): Int {
        return R.layout.item_grid_header
    }

    ...
}

class StringAdapter : ListAdapter<String, StringHolder>(DiffCallback()) {
    ...

    override fun getItemViewType(position: Int): Int {
        return R.layout.item_string
    }

    ...
}

 

'Android' 카테고리의 다른 글

Android RecyclerView - ConcatAdapter  (0) 2022.04.01
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함