
웹으로 오픈한 구글 플레이 스토어 페이지 화면입니다.
자세히 보시면 화면 아이템 레이아웃에 대한 간단한 규칙이 존재합니다.
이 레이아웃은 어떻게 구성되어 있을까요?
레아이웃을 간단히 분해 해보자면

제가 진행하던 프로젝트의 Main Fragment가 이런식으로 구현이 되어있었고,
처음에는 무식하게 NestedScrollView에 n개의 헤더뷰, n개의 recyclerview를 했는데,
이렇게 하므로써 경험했던 가장 큰 문제점들은
1. 새로운 아이템이 추가 되면 layout.xml 파일에 다시 추가 해야 한다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<헤더>
...
</헤더>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<에러메세지 뷰
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
...
위 내용들의 연속
...
</androidx.core.widget.NestedScrollView>
위와 같은 고통으로 인해 검색 전에 몇몇개의 앱을 관찰한 결과, 서두에 언급한 규칙이 있는것을 알게 되었습니다.
구현은 나름 간단합니다.(머리로는 이해했으나 코드로는 못써서 결국 샘플을 찾아봤지만..)
앞선 이미지를 통해 다시 한번 더 top-down방식으로 설명을 드려보겠습니다.

<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.hellovelog.view.ViewMainSectionTitle
... />
<androidx.recyclerview.widget.RecyclerView
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
data class Section (
val titleRes: Int,
val descriptionRes: Int,
val data: List<item>
...
)
onBindViewHolders와 viewHolder는 실제 아이템을 뷰로 나타는 역할을 하는데,override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseParentViewHolder {
val view = ItemTitleWithListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val childLayoutManager =
LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false).apply {
initialPrefetchItemCount = 3
isItemPrefetchEnabled = true
}
val viewHolder = ParentViewHolder(from, activity, view, childLayoutManager)
viewHolder.onCreate()
return viewHolder
}
override fun onBindViewHolder(holder: BaseParentViewHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
- onBindViewHolder( )에서 다시 자식 RecyclerView에 대한 세팅을 해주는 예시 입니다.
override fun bind(item: Statement) {
binding.title.apply {
setTitleText(item.titleRes)
...
}
val childAdapter = ChildAdapterFactory.create(item, activity, from)
binding.list.run {
layoutManager = linearLayoutManager
adapter = childAdapter
...
}
}
코드를 잠깐 보시면 ChildAdapterFactory라는게 보이실겁니다.
팩토리 디자인 패턴을 활용하여 작업을 하였는데 이렇게, 한 가장 큰 이유는 제가 진행하고 있는
프로젝트에서는 자식 RecyclerView에 사용되는 아이템 종류가 여러 가지 라서 각각의 아이템 타입에 맞는 Adapter를 생성하고 있습니다.
아래 링크는 자세하게 구현까지 포함이 되어있는 링크입니다. 위에 내용이 이해가 가신다면 바로 코드만 봐도 무방할듯합니다.
감사합니다.