feat(content): 전체 탭 카드 어댑터를 추가한다

This commit is contained in:
2026-06-25 11:54:05 +09:00
parent 0a97194b31
commit c1a21985fd
6 changed files with 122 additions and 6 deletions

View File

@@ -0,0 +1,48 @@
package kr.co.vividnext.sodalive.v2.main.content.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kr.co.vividnext.sodalive.databinding.ItemContentAudioCardBinding
import kr.co.vividnext.sodalive.extensions.loadUrl
import kr.co.vividnext.sodalive.v2.main.content.model.MainContentAllAudioUiModel
import kr.co.vividnext.sodalive.v2.widget.AudioContentCardSize
class ContentAllAudioCardAdapter(
private val onAudioClick: (Long) -> Unit = {}
) : RecyclerView.Adapter<ContentAllAudioCardAdapter.ViewHolder>() {
private var items: List<MainContentAllAudioUiModel> = emptyList()
fun submitItems(items: List<MainContentAllAudioUiModel>) {
this.items = items
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemContentAudioCardBinding.inflate(LayoutInflater.from(parent.context), parent, false),
onAudioClick
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
class ViewHolder(
private val binding: ItemContentAudioCardBinding,
private val onAudioClick: (Long) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: MainContentAllAudioUiModel) = with(binding.audioContentCard.root) {
setSize(AudioContentCardSize.Small)
setContent(item.title, item.creatorNickname)
setTags(item.tags)
setAdultVisible(item.showAdultBadge)
thumbnailView().loadUrl(item.imageUrl)
setOnClickListener { onAudioClick(item.audioContentId) }
}
}
}

View File

@@ -0,0 +1,48 @@
package kr.co.vividnext.sodalive.v2.main.content.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kr.co.vividnext.sodalive.databinding.ItemContentAllSeriesCardBinding
import kr.co.vividnext.sodalive.extensions.loadUrl
import kr.co.vividnext.sodalive.v2.main.content.model.MainContentAllSeriesUiModel
import kr.co.vividnext.sodalive.v2.widget.SeriesContentCardSize
class ContentAllSeriesCardAdapter(
private val onSeriesClick: (Long) -> Unit = {}
) : RecyclerView.Adapter<ContentAllSeriesCardAdapter.ViewHolder>() {
private var items: List<MainContentAllSeriesUiModel> = emptyList()
fun submitItems(items: List<MainContentAllSeriesUiModel>) {
this.items = items
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemContentAllSeriesCardBinding.inflate(LayoutInflater.from(parent.context), parent, false),
onSeriesClick
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
class ViewHolder(
private val binding: ItemContentAllSeriesCardBinding,
private val onSeriesClick: (Long) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: MainContentAllSeriesUiModel) = with(binding.seriesContentCard.root) {
setSize(SeriesContentCardSize.Small)
setContent(item.title, item.creatorNickname)
setOriginalVisible(item.showOriginalTag)
setAdultVisible(item.showAdultBadge)
thumbnailView().loadUrl(item.coverImageUrl)
setOnClickListener { onSeriesClick(item.seriesId) }
}
}
}

View File

@@ -9,8 +9,8 @@ fun RecyclerView.addContentHorizontalItemSpacing() {
if (itemDecorationCount == 0) addItemDecoration(ContentHorizontalItemDecoration())
}
fun RecyclerView.addContentGridItemSpacing() {
if (itemDecorationCount == 0) addItemDecoration(ContentGridItemDecoration())
fun RecyclerView.addContentGridItemSpacing(spanCount: Int = CONTENT_RECOMMENDED_GRID_SPAN_COUNT) {
if (itemDecorationCount == 0) addItemDecoration(ContentGridItemDecoration(spanCount))
}
private class ContentHorizontalItemDecoration : RecyclerView.ItemDecoration() {
@@ -22,15 +22,17 @@ private class ContentHorizontalItemDecoration : RecyclerView.ItemDecoration() {
}
}
private class ContentGridItemDecoration : RecyclerView.ItemDecoration() {
private class ContentGridItemDecoration(
private val spanCount: Int
) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val position = parent.getChildAdapterPosition(view)
if (position == RecyclerView.NO_POSITION) return
val isLeftColumn = position % GRID_SPAN_COUNT == 0
val isLeftColumn = position % spanCount == 0
val halfGap = GRID_ITEM_GAP_DP.dpToPx().toInt() / 2
outRect.left = if (isLeftColumn) 0 else halfGap
outRect.right = if (isLeftColumn) halfGap else 0
if (position >= GRID_SPAN_COUNT) outRect.top = GRID_ITEM_VERTICAL_GAP_DP.dpToPx().toInt()
if (position >= spanCount) outRect.top = GRID_ITEM_VERTICAL_GAP_DP.dpToPx().toInt()
}
}
@@ -38,4 +40,3 @@ private const val HORIZONTAL_ITEM_GAP_DP = 8
private const val GRID_ITEM_GAP_DP = 8
private const val GRID_ITEM_VERTICAL_GAP_DP = 28
const val CONTENT_RECOMMENDED_GRID_SPAN_COUNT = 2
private const val GRID_SPAN_COUNT = CONTENT_RECOMMENDED_GRID_SPAN_COUNT

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/gray_900" />
<corners android:radius="@dimen/radius_8" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="@dimen/radius_8" />
</shape>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<include
android:id="@+id/series_content_card"
layout="@layout/view_series_content_card" />
</FrameLayout>