chore(creator-ranking): 기존 카드 뷰를 제거한다

This commit is contained in:
2026-06-30 02:44:36 +09:00
parent 7c7aa0f442
commit 926e7eabd3
9 changed files with 0 additions and 828 deletions

View File

@@ -1,7 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
enum class CreatorRankingCardVariant {
Large,
Compact,
Horizontal
}

View File

@@ -1,190 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
import android.content.Context
import android.graphics.Outline
import android.graphics.RenderEffect
import android.graphics.Shader
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import kr.co.vividnext.sodalive.R
import kotlin.math.roundToInt
class CreatorRankingCompactCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private var image: ImageView? = null
private var dimGradient: View? = null
private var deltaGroup: View? = null
private var rankText: TextView? = null
private var deltaAmountText: TextView? = null
private var deltaIcon: ImageView? = null
private var nameText: TextView? = null
private var currentItem: CreatorRankingItem? = null
private var clickListener: ((CreatorRankingItem) -> Unit)? = null
override fun onFinishInflate() {
super.onFinishInflate()
image = findViewById(R.id.iv_creator_ranking_image)
dimGradient = findViewById(R.id.v_creator_ranking_dim_gradient)
deltaGroup = findViewById(R.id.ll_creator_ranking_delta)
rankText = findViewById(R.id.tv_creator_ranking_rank)
deltaAmountText = findViewById(R.id.tv_creator_ranking_delta_amount)
deltaIcon = findViewById(R.id.iv_creator_ranking_delta_icon)
nameText = findViewById(R.id.tv_creator_ranking_name)
clipToOutline = true
outlineProvider = roundOutlineProvider()
imageView().outlineProvider = roundOutlineProvider()
imageView().clipToOutline = true
}
fun bind(item: CreatorRankingItem) {
currentItem = item
requireNotNull(rankText).apply {
text = item.rank.toString()
applyCreatorRankingRankGradient()
}
bindDelta(item)
requireNotNull(nameText).apply {
text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info))
visibility = if (text.isNullOrBlank()) View.INVISIBLE else View.VISIBLE
}
dimGradient?.visibility = View.VISIBLE
applyAccessState(item)
}
fun setCardSize(size: CreatorRankingCardSize) {
layoutParams = (layoutParams ?: ViewGroup.LayoutParams(size.widthPx, size.heightPx)).apply {
width = size.widthPx
height = size.heightPx
}
positionViews(size)
}
fun imageView(): ImageView = requireNotNull(image)
fun setOnCreatorClick(listener: ((CreatorRankingItem) -> Unit)?) {
clickListener = listener
currentItem?.let(::applyAccessState)
}
private fun bindDelta(item: CreatorRankingItem) {
requireNotNull(deltaGroup).visibility = if (item.showRankChange) View.VISIBLE else View.GONE
if (!item.showRankChange) return
val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
applyDeltaContainer(presentation)
requireNotNull(deltaIcon).apply {
setImageResource(presentation.iconRes)
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
width = presentation.iconWidthDp.dpToPx()
height = presentation.iconHeightDp.dpToPx()
marginStart = presentation.iconMarginStartDp.dpToPx()
}
}
requireNotNull(deltaAmountText).apply {
text = presentation.amountText.orEmpty()
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
}
}
private fun applyDeltaContainer(presentation: CreatorRankingDeltaPresentation) {
requireNotNull(deltaGroup).apply {
setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0)
val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx() else 0
setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom)
}
}
private fun applyAccessState(item: CreatorRankingItem) {
applyBlur(item.isInaccessible)
isClickable = item.isTouchable && clickListener != null
setOnClickListener(if (isClickable) View.OnClickListener { clickListener?.invoke(item) } else null)
}
private fun positionViews(size: CreatorRankingCardSize) {
if (size.widthPx <= SMALL_THRESHOLD_PX) {
requireNotNull(rankText).textSize = 40f
requireNotNull(nameText).textSize = 14f
positionSmall(size)
} else {
requireNotNull(rankText).textSize = 54f
requireNotNull(nameText).textSize = 22f
positionMedium(size)
}
requireNotNull(rankText).applyCreatorRankingRankGradient()
}
private fun positionMedium(size: CreatorRankingCardSize) {
val scale = size.widthPx / 185f
requireNotNull(rankText).layoutParams = LayoutParams((56 * scale).roundToInt(), (70 * scale).roundToInt())
requireNotNull(rankText).setPadding(0, 0, 0, (6 * scale).roundToInt())
findViewById<View>(R.id.ll_creator_ranking_delta).layoutParams = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = (10 * scale).roundToInt()
topMargin = (70 * scale).roundToInt()
}
requireNotNull(nameText).layoutParams = LayoutParams(
(165 * scale).roundToInt(),
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = ((size.widthPx - (165 * scale)) / 2f).roundToInt()
topMargin = (145 * scale).roundToInt()
}
}
private fun positionSmall(size: CreatorRankingCardSize) {
val scale = size.widthPx / 122f
requireNotNull(rankText).layoutParams = LayoutParams(
(52 * scale).roundToInt(),
(50 * scale).roundToInt()
).apply {
leftMargin = 0
}
requireNotNull(rankText).setPadding(0, 0, 0, (5 * scale).roundToInt())
findViewById<View>(R.id.ll_creator_ranking_delta).layoutParams = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = (10 * scale).roundToInt()
topMargin = (50 * scale).roundToInt()
}
requireNotNull(nameText).layoutParams = LayoutParams(
(102 * scale).roundToInt(),
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = ((size.widthPx - (102 * scale)) / 2f).roundToInt()
topMargin = (98 * scale).roundToInt()
}
}
private fun applyBlur(enabled: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
imageView().setRenderEffect(
if (enabled) RenderEffect.createBlurEffect(16f, 16f, Shader.TileMode.CLAMP) else null
)
}
}
private fun roundOutlineProvider() = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, 14.dpToPx().toFloat())
}
}
private fun Int.dpToPx(): Int = (this * resources.displayMetrics.density).roundToInt()
private companion object {
const val SMALL_THRESHOLD_PX = 140
}
}

View File

@@ -1,149 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
import android.content.Context
import android.graphics.Outline
import android.graphics.RenderEffect
import android.graphics.Shader
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import kr.co.vividnext.sodalive.R
import kotlin.math.roundToInt
class CreatorRankingHorizontalCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private var rankGroup: View? = null
private var image: ImageView? = null
private var rankText: TextView? = null
private var deltaAmountText: TextView? = null
private var deltaIcon: ImageView? = null
private var nameText: TextView? = null
private var currentItem: CreatorRankingItem? = null
private var clickListener: ((CreatorRankingItem) -> Unit)? = null
override fun onFinishInflate() {
super.onFinishInflate()
rankGroup = findViewById(R.id.ll_creator_ranking_rank_group)
image = findViewById(R.id.iv_creator_ranking_image)
rankText = findViewById(R.id.tv_creator_ranking_rank)
deltaAmountText = findViewById(R.id.tv_creator_ranking_delta_amount)
deltaIcon = findViewById(R.id.iv_creator_ranking_delta_icon)
nameText = findViewById(R.id.tv_creator_ranking_name)
imageView().outlineProvider = roundOutlineProvider()
imageView().clipToOutline = true
}
fun bind(item: CreatorRankingItem) {
currentItem = item
requireNotNull(rankText).apply {
text = item.rank.toString()
applyCreatorRankingRankGradient()
}
bindDelta(item)
requireNotNull(nameText).text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info))
applyAccessState(item)
}
fun setCardSize(size: CreatorRankingCardSize) {
layoutParams = (layoutParams ?: ViewGroup.LayoutParams(size.widthPx, size.heightPx)).apply {
width = size.widthPx
height = size.heightPx
}
positionViews(size)
}
fun imageView(): ImageView = requireNotNull(image)
fun setOnCreatorClick(listener: ((CreatorRankingItem) -> Unit)?) {
clickListener = listener
currentItem?.let(::applyAccessState)
}
private fun bindDelta(item: CreatorRankingItem) {
val deltaGroup = findViewById<View>(R.id.ll_creator_ranking_delta)
deltaGroup.visibility = if (item.showRankChange) View.VISIBLE else View.GONE
if (!item.showRankChange) return
val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
applyDeltaContainer(presentation)
requireNotNull(deltaIcon).apply {
setImageResource(presentation.iconRes)
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
width = presentation.iconWidthDp.dpToPx()
height = presentation.iconHeightDp.dpToPx()
marginStart = presentation.iconMarginStartDp.dpToPx()
}
}
requireNotNull(deltaAmountText).apply {
text = presentation.amountText.orEmpty()
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
}
}
private fun applyDeltaContainer(presentation: CreatorRankingDeltaPresentation) {
findViewById<View>(R.id.ll_creator_ranking_delta).apply {
setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0)
val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx() else 0
setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom)
}
}
private fun applyAccessState(item: CreatorRankingItem) {
applyBlur(item.isInaccessible)
isClickable = item.isTouchable && clickListener != null
setOnClickListener(if (isClickable) View.OnClickListener { clickListener?.invoke(item) } else null)
}
private fun positionViews(size: CreatorRankingCardSize) {
val scale = size.widthPx / 374f
requireNotNull(rankGroup).layoutParams = LayoutParams(
(49 * scale).roundToInt(),
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = (14 * scale).roundToInt()
topMargin = (12 * scale).roundToInt()
}
requireNotNull(rankText).layoutParams = android.widget.LinearLayout.LayoutParams(
(48 * scale).roundToInt(),
(52 * scale).roundToInt()
)
requireNotNull(rankText).setPadding(0, 0, 0, (4 * scale).roundToInt())
requireNotNull(rankText).applyCreatorRankingRankGradient()
imageView().layoutParams = LayoutParams((80 * scale).roundToInt(), (80 * scale).roundToInt()).apply {
leftMargin = (77 * scale).roundToInt()
topMargin = (10 * scale).roundToInt()
}
requireNotNull(nameText).layoutParams = LayoutParams(
(189 * scale).roundToInt(),
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = (171 * scale).roundToInt()
topMargin = (39 * scale).roundToInt()
}
}
private fun applyBlur(enabled: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
imageView().setRenderEffect(
if (enabled) RenderEffect.createBlurEffect(16f, 16f, Shader.TileMode.CLAMP) else null
)
}
}
private fun roundOutlineProvider() = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, 14.dpToPx().toFloat())
}
}
private fun Int.dpToPx(): Int = (this * resources.displayMetrics.density).roundToInt()
}

View File

@@ -1,156 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
import android.content.Context
import android.graphics.Outline
import android.graphics.RenderEffect
import android.graphics.Shader
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import kr.co.vividnext.sodalive.R
import kotlin.math.roundToInt
class CreatorRankingLargeCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private var image: ImageView? = null
private var dimGradient: View? = null
private var deltaGroup: View? = null
private var rankText: TextView? = null
private var deltaAmountText: TextView? = null
private var deltaIcon: ImageView? = null
private var nameText: TextView? = null
private var currentItem: CreatorRankingItem? = null
private var clickListener: ((CreatorRankingItem) -> Unit)? = null
override fun onFinishInflate() {
super.onFinishInflate()
image = findViewById(R.id.iv_creator_ranking_image)
dimGradient = findViewById(R.id.v_creator_ranking_dim_gradient)
deltaGroup = findViewById(R.id.ll_creator_ranking_delta)
rankText = findViewById(R.id.tv_creator_ranking_rank)
deltaAmountText = findViewById(R.id.tv_creator_ranking_delta_amount)
deltaIcon = findViewById(R.id.iv_creator_ranking_delta_icon)
nameText = findViewById(R.id.tv_creator_ranking_name)
clipToOutline = true
outlineProvider = roundOutlineProvider()
imageView().outlineProvider = roundOutlineProvider()
imageView().clipToOutline = true
}
fun bind(item: CreatorRankingItem) {
currentItem = item
requireNotNull(rankText).apply {
text = item.rank.toString()
applyCreatorRankingRankGradient()
}
bindDelta(item)
requireNotNull(nameText).apply {
text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info))
visibility = if (text.isNullOrBlank()) View.INVISIBLE else View.VISIBLE
}
dimGradient?.visibility = View.VISIBLE
applyAccessState(item)
}
fun setCardSize(size: CreatorRankingCardSize) {
layoutParams = (layoutParams ?: ViewGroup.LayoutParams(size.widthPx, size.heightPx)).apply {
width = size.widthPx
height = size.heightPx
}
positionViews(size)
}
fun imageView(): ImageView = requireNotNull(image)
fun setOnCreatorClick(listener: ((CreatorRankingItem) -> Unit)?) {
clickListener = listener
currentItem?.let(::applyAccessState)
}
private fun bindDelta(item: CreatorRankingItem) {
requireNotNull(deltaGroup).visibility = if (item.showRankChange) View.VISIBLE else View.GONE
if (!item.showRankChange) return
val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
applyDeltaContainer(presentation)
requireNotNull(deltaIcon).apply {
setImageResource(presentation.iconRes)
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
width = presentation.iconWidthDp.dpToPx()
height = presentation.iconHeightDp.dpToPx()
marginStart = presentation.iconMarginStartDp.dpToPx()
}
}
requireNotNull(deltaAmountText).apply {
text = presentation.amountText.orEmpty()
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
}
}
private fun applyDeltaContainer(presentation: CreatorRankingDeltaPresentation) {
requireNotNull(deltaGroup).apply {
setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0)
val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx() else 0
setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom)
}
}
private fun applyAccessState(item: CreatorRankingItem) {
applyBlur(item.isInaccessible)
isClickable = item.isTouchable && clickListener != null
setOnClickListener(if (isClickable) View.OnClickListener { clickListener?.invoke(item) } else null)
}
private fun positionViews(size: CreatorRankingCardSize) {
val scale = size.widthPx / FIGMA_SIZE.toFloat()
requireNotNull(rankText).layoutParams = LayoutParams((86 * scale).roundToInt(), (116 * scale).roundToInt()).apply {
leftMargin = 0
topMargin = 0
}
requireNotNull(rankText).setPadding(0, 0, 0, (10 * scale).roundToInt())
requireNotNull(rankText).applyCreatorRankingRankGradient()
requireNotNull(nameText).layoutParams = LayoutParams(
(334 * scale).roundToInt(),
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = ((size.widthPx - (334 * scale)) / 2f).roundToInt()
topMargin = (305 * scale).roundToInt()
}
findViewById<View>(R.id.ll_creator_ranking_delta).layoutParams = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
leftMargin = (20 * scale).roundToInt()
topMargin = (116 * scale).roundToInt()
}
}
private fun applyBlur(enabled: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
imageView().setRenderEffect(
if (enabled) RenderEffect.createBlurEffect(16f, 16f, Shader.TileMode.CLAMP) else null
)
}
}
private fun roundOutlineProvider() = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, 14.dpToPx().toFloat())
}
}
private fun Int.dpToPx(): Int = (this * resources.displayMetrics.density).roundToInt()
private companion object {
const val FIGMA_SIZE = 374
}
}

View File

@@ -1,35 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
object CreatorRankingLayoutCalculator {
private const val HORIZONTAL_FIGMA_WIDTH = 374
private const val HORIZONTAL_FIGMA_HEIGHT = 100
fun calculate(
parentWidthPx: Int,
parentHorizontalPaddingPx: Int = 0,
horizontalGapPx: Int,
placement: CreatorRankingPlacement
): CreatorRankingCardSize {
require(parentWidthPx > 0) { "parentWidthPx must be > 0." }
require(parentHorizontalPaddingPx >= 0) { "parentHorizontalPaddingPx must be >= 0." }
require(horizontalGapPx >= 0) { "horizontalGapPx must be >= 0." }
require(placement.itemsPerRow > 0) { "itemsPerRow must be > 0." }
val totalGap = horizontalGapPx * (placement.itemsPerRow - 1)
val availableWidth = parentWidthPx - parentHorizontalPaddingPx
require(availableWidth > 0) { "available width must be > 0." }
val width = (availableWidth - totalGap) / placement.itemsPerRow
val height = when (placement.variant) {
CreatorRankingCardVariant.Large,
CreatorRankingCardVariant.Compact -> width
CreatorRankingCardVariant.Horizontal -> (width * HORIZONTAL_FIGMA_HEIGHT) / HORIZONTAL_FIGMA_WIDTH
}
return CreatorRankingCardSize(widthPx = width, heightPx = height)
}
}
data class CreatorRankingCardSize(
val widthPx: Int,
val heightPx: Int
)

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingCompactCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_creator_ranking_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_creator_ranking_image"
android:contentDescription="@null"
android:scaleType="centerCrop" />
<View
android:id="@+id/v_creator_ranking_dim_gradient"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_creator_ranking_dim_gradient" />
<TextView
android:id="@+id/tv_creator_ranking_rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pattaya_regular"
android:gravity="center"
android:includeFontPadding="false"
android:shadowColor="#7A000000"
android:shadowRadius="4"
android:textColor="@color/white"
android:textSize="54sp"
tools:text="2" />
<LinearLayout
android:id="@+id/ll_creator_ranking_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_creator_ranking_delta"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="4dp">
<TextView
android:id="@+id/tv_creator_ranking_delta_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/medium"
android:includeFontPadding="false"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="4" />
<ImageView
android:id="@+id/iv_creator_ranking_delta_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="2dp"
android:contentDescription="@null"
tools:src="@drawable/ic_rank_caret_increase" />
</LinearLayout>
<TextView
android:id="@+id/tv_creator_ranking_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/bold"
android:gravity="center"
android:includeFontPadding="false"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="22sp"
tools:text="크리에이터 이름" />
</kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingCompactCardView>

View File

@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingHorizontalCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_creator_ranking_rank_group"
android:layout_width="49dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_creator_ranking_rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pattaya_regular"
android:gravity="center"
android:includeFontPadding="false"
android:shadowColor="#7A000000"
android:shadowRadius="4"
android:textColor="@color/white"
android:textSize="40sp"
tools:text="11" />
<LinearLayout
android:id="@+id/ll_creator_ranking_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_creator_ranking_delta"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="4dp">
<TextView
android:id="@+id/tv_creator_ranking_delta_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/medium"
android:includeFontPadding="false"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="4" />
<ImageView
android:id="@+id/iv_creator_ranking_delta_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="2dp"
android:contentDescription="@null"
tools:src="@drawable/ic_rank_caret_increase" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/iv_creator_ranking_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/bg_creator_ranking_image"
android:contentDescription="@null"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_creator_ranking_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/bold"
android:includeFontPadding="false"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="크리에이터 이름" />
</kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingHorizontalCardView>

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingLargeCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_creator_ranking_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_creator_ranking_image"
android:contentDescription="@null"
android:scaleType="centerCrop" />
<View
android:id="@+id/v_creator_ranking_dim_gradient"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_creator_ranking_dim_gradient" />
<TextView
android:id="@+id/tv_creator_ranking_rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pattaya_regular"
android:gravity="center"
android:includeFontPadding="false"
android:shadowColor="#7A000000"
android:shadowRadius="4"
android:textColor="@color/white"
android:textSize="96sp"
tools:text="1" />
<LinearLayout
android:id="@+id/ll_creator_ranking_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_creator_ranking_delta"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="4dp">
<TextView
android:id="@+id/tv_creator_ranking_delta_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/medium"
android:includeFontPadding="false"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="4" />
<ImageView
android:id="@+id/iv_creator_ranking_delta_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="2dp"
android:contentDescription="@null"
tools:src="@drawable/ic_rank_caret_increase" />
</LinearLayout>
<TextView
android:id="@+id/tv_creator_ranking_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/bold"
android:gravity="center"
android:includeFontPadding="false"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="32sp"
tools:text="크리에이터 이름" />
</kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingLargeCardView>

View File

@@ -1,68 +0,0 @@
package kr.co.vividnext.sodalive.v2.widget.creatorranking
import org.junit.Assert.assertEquals
import org.junit.Test
class CreatorRankingLayoutCalculatorTest {
@Test
fun `large card fills available width as square`() {
val size = CreatorRankingLayoutCalculator.calculate(
parentWidthPx = 374,
horizontalGapPx = 4,
placement = CreatorRankingPlacement(CreatorRankingCardVariant.Large, itemsPerRow = 1)
)
assertEquals(374, size.widthPx)
assertEquals(374, size.heightPx)
}
@Test
fun `large card excludes parent horizontal padding from available width`() {
val size = CreatorRankingLayoutCalculator.calculate(
parentWidthPx = 374,
parentHorizontalPaddingPx = 40,
horizontalGapPx = 4,
placement = CreatorRankingPlacement(CreatorRankingCardVariant.Large, itemsPerRow = 1)
)
assertEquals(334, size.widthPx)
assertEquals(334, size.heightPx)
}
@Test
fun `compact card can use two columns`() {
val size = CreatorRankingLayoutCalculator.calculate(
parentWidthPx = 374,
horizontalGapPx = 4,
placement = CreatorRankingPlacement(CreatorRankingCardVariant.Compact, itemsPerRow = 2)
)
assertEquals(185, size.widthPx)
assertEquals(185, size.heightPx)
}
@Test
fun `compact card can use three columns`() {
val size = CreatorRankingLayoutCalculator.calculate(
parentWidthPx = 374,
horizontalGapPx = 4,
placement = CreatorRankingPlacement(CreatorRankingCardVariant.Compact, itemsPerRow = 3)
)
assertEquals(122, size.widthPx)
assertEquals(122, size.heightPx)
}
@Test
fun `horizontal card keeps figma aspect ratio`() {
val size = CreatorRankingLayoutCalculator.calculate(
parentWidthPx = 374,
horizontalGapPx = 4,
placement = CreatorRankingPlacement(CreatorRankingCardVariant.Horizontal, itemsPerRow = 1)
)
assertEquals(374, size.widthPx)
assertEquals(100, size.heightPx)
}
}