refactor(creator-ranking): 어댑터 뷰 타입을 정리한다

This commit is contained in:
2026-06-30 02:44:19 +09:00
parent 86be8e4af1
commit 7c7aa0f442
5 changed files with 104 additions and 303 deletions

View File

@@ -185,6 +185,9 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
private fun setUpCreatorRankingAdapter() {
binding.rvHomeCreatorRankings.apply {
layoutManager = CreatorRankingAdapter.createGridLayoutManager(requireContext())
if (itemDecorationCount == 0) {
addItemDecoration(CreatorRankingAdapter.createItemDecoration(requireContext()))
}
adapter = creatorRankingAdapter
}
}

View File

@@ -1,7 +1,9 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
import android.content.Context
import android.graphics.Rect
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.GridLayoutManager
@@ -16,26 +18,22 @@ class CreatorRankingAdapter(
private val items = mutableListOf<CreatorRankingItem>()
override fun getItemViewType(position: Int): Int = when (CreatorRankingPlacement.fromRank(items[position].rank).variant) {
CreatorRankingCardVariant.Large -> VIEW_TYPE_LARGE
CreatorRankingCardVariant.Compact -> VIEW_TYPE_COMPACT
CreatorRankingCardVariant.Horizontal -> VIEW_TYPE_HORIZONTAL
override fun getItemViewType(position: Int): Int {
val placement = CreatorRankingPlacement.fromRank(items[position].rank)
return when (placement.viewType) {
CreatorRankingViewType.TopTen -> VIEW_TYPE_TOP_TEN
CreatorRankingViewType.Lower -> VIEW_TYPE_LOWER
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
VIEW_TYPE_LARGE -> LargeViewHolder(
inflater.inflate(R.layout.view_creator_ranking_large_card, parent, false) as CreatorRankingLargeCardView,
parent
VIEW_TYPE_TOP_TEN -> TopTenViewHolder(
inflater.inflate(R.layout.view_creator_ranking_top_card, parent, false) as CreatorRankingTopCardView
)
VIEW_TYPE_COMPACT -> CompactViewHolder(
inflater.inflate(R.layout.view_creator_ranking_compact_card, parent, false) as CreatorRankingCompactCardView,
parent
)
VIEW_TYPE_HORIZONTAL -> HorizontalViewHolder(
inflater.inflate(R.layout.view_creator_ranking_horizontal_card, parent, false) as CreatorRankingHorizontalCardView,
parent
VIEW_TYPE_LOWER -> LowerViewHolder(
inflater.inflate(R.layout.view_creator_ranking_lower_row, parent, false) as CreatorRankingLowerRowView
)
else -> error("Unknown viewType: $viewType")
}
@@ -44,9 +42,8 @@ class CreatorRankingAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position]
when (holder) {
is LargeViewHolder -> holder.bind(item)
is CompactViewHolder -> holder.bind(item)
is HorizontalViewHolder -> holder.bind(item)
is TopTenViewHolder -> holder.bind(item)
is LowerViewHolder -> holder.bind(item)
}
}
@@ -58,66 +55,37 @@ class CreatorRankingAdapter(
notifyDataSetChanged()
}
private inner class LargeViewHolder(
private val view: CreatorRankingLargeCardView,
private val parent: ViewGroup
private inner class TopTenViewHolder(
private val view: CreatorRankingTopCardView
) : RecyclerView.ViewHolder(view) {
fun bind(item: CreatorRankingItem) {
bindCommon(view, item, parent)
bindCommon(view, item)
view.bind(item)
view.setOnCreatorClick(onClickItem)
}
}
private inner class CompactViewHolder(
private val view: CreatorRankingCompactCardView,
private val parent: ViewGroup
private inner class LowerViewHolder(
private val view: CreatorRankingLowerRowView
) : RecyclerView.ViewHolder(view) {
fun bind(item: CreatorRankingItem) {
bindCommon(view, item, parent)
view.bind(item)
view.setOnCreatorClick(onClickItem)
}
}
private inner class HorizontalViewHolder(
private val view: CreatorRankingHorizontalCardView,
private val parent: ViewGroup
) : RecyclerView.ViewHolder(view) {
fun bind(item: CreatorRankingItem) {
bindCommon(view, item, parent)
bindCommon(view, item)
view.bind(item)
view.setOnCreatorClick(onClickItem)
}
}
private fun bindCommon(
view: CreatorRankingLargeCardView,
item: CreatorRankingItem,
parent: ViewGroup
view: CreatorRankingTopCardView,
item: CreatorRankingItem
) {
val size = calculateSize(item, parent)
view.setCardSize(size)
view.imageView().loadCreatorImage(item)
}
private fun bindCommon(
view: CreatorRankingCompactCardView,
item: CreatorRankingItem,
parent: ViewGroup
view: CreatorRankingLowerRowView,
item: CreatorRankingItem
) {
val size = calculateSize(item, parent)
view.setCardSize(size)
view.imageView().loadCreatorImage(item)
}
private fun bindCommon(
view: CreatorRankingHorizontalCardView,
item: CreatorRankingItem,
parent: ViewGroup
) {
val size = calculateSize(item, parent)
view.setCardSize(size)
view.imageView().loadCreatorImage(item)
}
@@ -130,21 +98,6 @@ class CreatorRankingAdapter(
}
}
private fun calculateSize(
item: CreatorRankingItem,
parent: ViewGroup
): CreatorRankingCardSize {
val parentWidth = parent.width.takeIf { it > 0 } ?: parent.resources.displayMetrics.widthPixels
return CreatorRankingLayoutCalculator.calculate(
parentWidthPx = parentWidth,
parentHorizontalPaddingPx = parent.paddingLeft + parent.paddingRight,
horizontalGapPx = HORIZONTAL_GAP_DP.dpToPx(parent),
placement = CreatorRankingPlacement.fromRank(item.rank)
)
}
private fun Int.dpToPx(parent: ViewGroup): Int = (this * parent.resources.displayMetrics.density).roundToInt()
companion object {
const val GRID_SPAN_COUNT = 6
@@ -152,6 +105,10 @@ class CreatorRankingAdapter(
spanSizeLookup = createSpanSizeLookup()
}
fun createItemDecoration(context: Context): RecyclerView.ItemDecoration {
return CreatorRankingItemDecoration(HORIZONTAL_GAP_DP.dpToPx(context))
}
fun createSpanSizeLookup(): GridLayoutManager.SpanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int = when (CreatorRankingPlacement.fromRank(position + 1).itemsPerRow) {
1 -> GRID_SPAN_COUNT
@@ -161,9 +118,50 @@ class CreatorRankingAdapter(
}
}
private const val VIEW_TYPE_LARGE = 1
private const val VIEW_TYPE_COMPACT = 2
private const val VIEW_TYPE_HORIZONTAL = 3
private const val HORIZONTAL_GAP_DP = 4
private const val VIEW_TYPE_TOP_TEN = 1
private const val VIEW_TYPE_LOWER = 2
private const val HORIZONTAL_GAP_DP = 8
private fun Int.dpToPx(context: Context): Int = (this * context.resources.displayMetrics.density).roundToInt()
}
}
internal class CreatorRankingItemDecoration(
private val spacingPx: Int
) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
val itemCount = parent.adapter?.itemCount ?: return
if (position == RecyclerView.NO_POSITION) return
outRect.set(offsetsForPosition(position, itemCount))
}
fun offsetsForPosition(
adapterPosition: Int,
itemCount: Int
): Rect {
val placement = CreatorRankingPlacement.fromRank(adapterPosition + 1)
val indexInRow = adapterPosition.indexInRankingRow(placement.itemsPerRow)
return Rect().apply {
left = indexInRow * spacingPx / placement.itemsPerRow
right = spacingPx - (indexInRow + 1) * spacingPx / placement.itemsPerRow
if (adapterPosition < itemCount - 1) bottom = spacingPx
}
}
private fun Int.indexInRankingRow(itemsPerRow: Int): Int {
return when (this) {
0 -> 0
in 1..6 -> (this - 1) % itemsPerRow
in 7..9 -> (this - 7) % itemsPerRow
else -> 0
}
}
}

View File

@@ -360,5 +360,5 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_tab_bar_home"
tools:listitem="@layout/view_creator_ranking_horizontal_card" />
tools:listitem="@layout/view_creator_ranking_lower_row" />
</androidx.constraintlayout.widget.ConstraintLayout>