fix(creator-ranking): 카드 UI 크기를 반응형 적용한다

This commit is contained in:
2026-07-10 10:16:18 +09:00
parent f477b563a2
commit 991d70f22b
4 changed files with 38 additions and 27 deletions

View File

@@ -14,6 +14,7 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScale
import kotlin.math.max import kotlin.math.max
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -61,16 +62,17 @@ class CreatorRankingLowerRowView @JvmOverloads constructor(
fun bind(item: CreatorRankingItem) { fun bind(item: CreatorRankingItem) {
currentItem = item currentItem = item
val style = CreatorRankingTextStyle.fromRank(item.rank) val scale = RankingResponsiveScale.fromResources(resources)
val style = CreatorRankingTextStyle.fromRank(item.rank).scaledBy(scale)
requireNotNull(rankText).apply { requireNotNull(rankText).apply {
text = item.rank.toString() text = item.rank.toString()
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp)
applyCreatorRankingRankGradient() applyCreatorRankingRankGradient()
} }
bindDelta(item, style) bindDelta(item, style)
requireNotNull(nameText).apply { requireNotNull(nameText).apply {
text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info)) text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info))
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.nameTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.nameTextSizeSp)
} }
applyAccessState(item) applyAccessState(item)
} }
@@ -84,32 +86,36 @@ class CreatorRankingLowerRowView @JvmOverloads constructor(
private fun bindDelta( private fun bindDelta(
item: CreatorRankingItem, item: CreatorRankingItem,
style: CreatorRankingTextStyle style: CreatorRankingScaledTextStyle
) { ) {
requireNotNull(deltaGroup).visibility = if (item.showRankChange) VISIBLE else GONE requireNotNull(deltaGroup).visibility = if (item.showRankChange) VISIBLE else GONE
if (!item.showRankChange) return if (!item.showRankChange) return
val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount) val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
applyDeltaContainer(presentation) val scale = RankingResponsiveScale.fromResources(resources)
applyDeltaContainer(presentation, scale)
requireNotNull(deltaIcon).apply { requireNotNull(deltaIcon).apply {
setImageResource(presentation.iconRes) setImageResource(presentation.iconRes)
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply { layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
width = presentation.iconWidthDp.dpToPx() width = presentation.iconWidthDp.dpToPx(scale)
height = presentation.iconHeightDp.dpToPx() height = presentation.iconHeightDp.dpToPx(scale)
marginStart = presentation.iconMarginStartDp.dpToPx() marginStart = presentation.iconMarginStartDp.dpToPx(scale)
} }
} }
requireNotNull(deltaAmountText).apply { requireNotNull(deltaAmountText).apply {
text = presentation.amountText.orEmpty() text = presentation.amountText.orEmpty()
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp)
visibility = if (presentation.showAmount) VISIBLE else GONE visibility = if (presentation.showAmount) VISIBLE else GONE
} }
} }
private fun applyDeltaContainer(presentation: CreatorRankingDeltaPresentation) { private fun applyDeltaContainer(
presentation: CreatorRankingDeltaPresentation,
scale: Float
) {
requireNotNull(deltaGroup).apply { requireNotNull(deltaGroup).apply {
setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0) setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0)
val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx() else 0 val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx(scale) else 0
setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom) setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom)
} }
} }
@@ -134,7 +140,7 @@ class CreatorRankingLowerRowView @JvmOverloads constructor(
} }
} }
private fun Int.dpToPx(): Int = (this * resources.displayMetrics.density).roundToInt() private fun Int.dpToPx(scale: Float = 1f): Int = (this * scale * resources.displayMetrics.density).roundToInt()
private companion object { private companion object {
const val FIGMA_HEIGHT_RATIO_NUMERATOR = 100 const val FIGMA_HEIGHT_RATIO_NUMERATOR = 100

View File

@@ -8,12 +8,12 @@ import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider import android.view.ViewOutlineProvider
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScale
import kotlin.math.roundToInt import kotlin.math.roundToInt
class CreatorRankingTopCardView @JvmOverloads constructor( class CreatorRankingTopCardView @JvmOverloads constructor(
@@ -57,17 +57,18 @@ class CreatorRankingTopCardView @JvmOverloads constructor(
fun bind(item: CreatorRankingItem) { fun bind(item: CreatorRankingItem) {
currentItem = item currentItem = item
val style = CreatorRankingTextStyle.fromRank(item.rank) val scale = RankingResponsiveScale.fromResources(resources)
val style = CreatorRankingTextStyle.fromRank(item.rank).scaledBy(scale)
applyMargins(CreatorRankingTopCardMargin.fromRank(item.rank)) applyMargins(CreatorRankingTopCardMargin.fromRank(item.rank))
requireNotNull(rankText).apply { requireNotNull(rankText).apply {
text = item.rank.toString() text = item.rank.toString()
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp)
applyCreatorRankingRankGradient() applyCreatorRankingRankGradient()
} }
bindDelta(item, style) bindDelta(item, style)
requireNotNull(nameText).apply { requireNotNull(nameText).apply {
text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info)) text = item.displayName(context.getString(R.string.creator_ranking_inaccessible_info))
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.nameTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.nameTextSizeSp)
visibility = if (text.isNullOrBlank()) INVISIBLE else VISIBLE visibility = if (text.isNullOrBlank()) INVISIBLE else VISIBLE
} }
dimGradient?.visibility = VISIBLE dimGradient?.visibility = VISIBLE
@@ -96,32 +97,36 @@ class CreatorRankingTopCardView @JvmOverloads constructor(
private fun bindDelta( private fun bindDelta(
item: CreatorRankingItem, item: CreatorRankingItem,
style: CreatorRankingTextStyle style: CreatorRankingScaledTextStyle
) { ) {
requireNotNull(deltaGroup).visibility = if (item.showRankChange) VISIBLE else GONE requireNotNull(deltaGroup).visibility = if (item.showRankChange) VISIBLE else GONE
if (!item.showRankChange) return if (!item.showRankChange) return
val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount) val presentation = CreatorRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
applyDeltaContainer(presentation) val scale = RankingResponsiveScale.fromResources(resources)
applyDeltaContainer(presentation, scale)
requireNotNull(deltaIcon).apply { requireNotNull(deltaIcon).apply {
setImageResource(presentation.iconRes) setImageResource(presentation.iconRes)
layoutParams = (layoutParams as MarginLayoutParams).apply { layoutParams = (layoutParams as MarginLayoutParams).apply {
width = presentation.iconWidthDp.dpToPx() width = presentation.iconWidthDp.dpToPx(scale)
height = presentation.iconHeightDp.dpToPx() height = presentation.iconHeightDp.dpToPx(scale)
marginStart = presentation.iconMarginStartDp.dpToPx() marginStart = presentation.iconMarginStartDp.dpToPx(scale)
} }
} }
requireNotNull(deltaAmountText).apply { requireNotNull(deltaAmountText).apply {
text = presentation.amountText.orEmpty() text = presentation.amountText.orEmpty()
setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp.toFloat()) setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp)
visibility = if (presentation.showAmount) VISIBLE else GONE visibility = if (presentation.showAmount) VISIBLE else GONE
} }
} }
private fun applyDeltaContainer(presentation: CreatorRankingDeltaPresentation) { private fun applyDeltaContainer(
presentation: CreatorRankingDeltaPresentation,
scale: Float
) {
requireNotNull(deltaGroup).apply { requireNotNull(deltaGroup).apply {
setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0) setBackgroundResource(if (presentation.showPillBackground) R.drawable.bg_creator_ranking_delta else 0)
val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx() else 0 val horizontalPadding = if (presentation.showPillBackground) 4.dpToPx(scale) else 0
setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom) setPadding(horizontalPadding, paddingTop, horizontalPadding, paddingBottom)
} }
} }
@@ -146,5 +151,5 @@ class CreatorRankingTopCardView @JvmOverloads constructor(
} }
} }
private fun Int.dpToPx(): Int = (this * resources.displayMetrics.density).roundToInt() private fun Int.dpToPx(scale: Float = 1f): Int = (this * scale * resources.displayMetrics.density).roundToInt()
} }

View File

@@ -21,7 +21,7 @@
android:id="@+id/tv_creator_ranking_rank" android:id="@+id/tv_creator_ranking_rank"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/phosphate_solid" android:fontFamily="@font/pattaya_regular"
android:gravity="center" android:gravity="center"
android:shadowColor="#7A000000" android:shadowColor="#7A000000"
android:shadowRadius="4" android:shadowRadius="4"

View File

@@ -41,7 +41,7 @@
android:id="@+id/tv_creator_ranking_rank" android:id="@+id/tv_creator_ranking_rank"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/phosphate_solid" android:fontFamily="@font/pattaya_regular"
android:gravity="center" android:gravity="center"
android:padding="0dp" android:padding="0dp"
android:shadowColor="#7A000000" android:shadowColor="#7A000000"