feat(content): 추천 공통 오디오 카드를 추가한다

This commit is contained in:
2026-06-23 17:17:33 +09:00
parent 0ea2a10554
commit 27add8b244
4 changed files with 80 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
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.ContentAudioCardUiModel
import kr.co.vividnext.sodalive.v2.widget.AudioContentCardSize
class ContentAudioCardAdapter(
private val cardSize: AudioContentCardSize,
private val onAudioClick: (ContentAudioCardUiModel) -> Unit = {}
) : RecyclerView.Adapter<ContentAudioCardAdapter.ViewHolder>() {
private var items: List<ContentAudioCardUiModel> = emptyList()
fun submitItems(items: List<ContentAudioCardUiModel>) {
this.items = items
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemContentAudioCardBinding.inflate(LayoutInflater.from(parent.context), parent, false),
cardSize,
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 cardSize: AudioContentCardSize,
private val onAudioClick: (ContentAudioCardUiModel) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: ContentAudioCardUiModel) = with(binding.audioContentCard.root) {
setSize(cardSize)
setContent(item.title, item.creatorNickname)
setTags(item.tags)
setAdultVisible(item.showAdultBadge)
thumbnailView().loadUrl(item.imageUrl)
setOnClickListener { onAudioClick(item) }
}
}
}

View File

@@ -26,6 +26,7 @@ class AudioContentCardView @JvmOverloads constructor(
private var thumbnail: ImageView? = null private var thumbnail: ImageView? = null
private var topTagContainer: LinearLayout? = null private var topTagContainer: LinearLayout? = null
private var bottomTagContainer: LinearLayout? = null private var bottomTagContainer: LinearLayout? = null
private var adultBadge: ImageView? = null
private var labelContainer: LinearLayout? = null private var labelContainer: LinearLayout? = null
private var titleText: TextView? = null private var titleText: TextView? = null
private var creatorText: TextView? = null private var creatorText: TextView? = null
@@ -40,6 +41,7 @@ class AudioContentCardView @JvmOverloads constructor(
thumbnail = findViewById(R.id.iv_audio_content_thumbnail) thumbnail = findViewById(R.id.iv_audio_content_thumbnail)
topTagContainer = findViewById(R.id.ll_audio_content_tag_top) topTagContainer = findViewById(R.id.ll_audio_content_tag_top)
bottomTagContainer = findViewById(R.id.ll_audio_content_tag_bottom) bottomTagContainer = findViewById(R.id.ll_audio_content_tag_bottom)
adultBadge = findViewById(R.id.iv_audio_content_adult_badge)
labelContainer = findViewById(R.id.ll_audio_content_label) labelContainer = findViewById(R.id.ll_audio_content_label)
titleText = findViewById(R.id.tv_audio_content_title) titleText = findViewById(R.id.tv_audio_content_title)
creatorText = findViewById(R.id.tv_audio_content_creator) creatorText = findViewById(R.id.tv_audio_content_creator)
@@ -90,6 +92,10 @@ class AudioContentCardView @JvmOverloads constructor(
fun thumbnailView(): ImageView = requireNotNull(thumbnail) fun thumbnailView(): ImageView = requireNotNull(thumbnail)
fun setAdultVisible(isVisible: Boolean) {
requireNotNull(adultBadge).visibility = if (isVisible) VISIBLE else GONE
}
fun setTags(tags: Set<AudioContentTag>) { fun setTags(tags: Set<AudioContentTag>) {
renderTags(requireNotNull(topTagContainer), orderedAudioContentTopTags(tags)) renderTags(requireNotNull(topTagContainer), orderedAudioContentTopTags(tags))
renderTags(requireNotNull(bottomTagContainer), orderedAudioContentBottomTags(tags)) renderTags(requireNotNull(bottomTagContainer), orderedAudioContentBottomTags(tags))
@@ -205,6 +211,7 @@ class AudioContentCardView @JvmOverloads constructor(
thumbnail != null && thumbnail != null &&
topTagContainer != null && topTagContainer != null &&
bottomTagContainer != null && bottomTagContainer != null &&
adultBadge != null &&
labelContainer != null && labelContainer != null &&
titleText != null && titleText != null &&
creatorText != null creatorText != null

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/audio_content_card"
layout="@layout/view_audio_content_card" />
</FrameLayout>

View File

@@ -18,6 +18,19 @@
android:contentDescription="@null" android:contentDescription="@null"
android:scaleType="centerCrop" /> android:scaleType="centerCrop" />
<ImageView
android:id="@+id/iv_audio_content_adult_badge"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="top|end"
android:layout_marginTop="@dimen/spacing_6"
android:layout_marginEnd="@dimen/spacing_6"
android:background="@drawable/bg_creator_channel_live_adult_badge"
android:contentDescription="@null"
android:padding="2dp"
android:src="@drawable/ic_new_shield_small"
android:visibility="gone" />
<LinearLayout <LinearLayout
android:id="@+id/ll_audio_content_tag_top" android:id="@+id/ll_audio_content_tag_top"
android:layout_width="wrap_content" android:layout_width="wrap_content"