fix(content-ranking): 카드 UI 크기를 반응형 적용한다
This commit is contained in:
@@ -6,6 +6,7 @@ import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewOutlineProvider
|
||||
@@ -13,6 +14,7 @@ import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScale
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
open class ContentRankingGridCardView @JvmOverloads constructor(
|
||||
@@ -29,6 +31,7 @@ open class ContentRankingGridCardView @JvmOverloads constructor(
|
||||
private var titleText: TextView? = null
|
||||
private var creatorText: TextView? = null
|
||||
private var currentItem: ContentRankingItem? = null
|
||||
private var currentTextStyle: ContentRankingTextStyle? = null
|
||||
private var clickListener: ((ContentRankingItem) -> Unit)? = null
|
||||
|
||||
override fun onFinishInflate() {
|
||||
@@ -48,11 +51,13 @@ open class ContentRankingGridCardView @JvmOverloads constructor(
|
||||
|
||||
fun bind(item: ContentRankingItem) {
|
||||
currentItem = item
|
||||
val textStyle = currentTextStyle ?: defaultTextStyle()
|
||||
applyTextStyle(textStyle)
|
||||
requireNotNull(rankText).apply {
|
||||
text = item.rank.toString()
|
||||
applyContentRankingRankGradient()
|
||||
}
|
||||
bindDelta(item)
|
||||
bindDelta(item, textStyle)
|
||||
requireNotNull(titleText).apply {
|
||||
text = item.displayContentName(context.getString(R.string.content_ranking_inaccessible_info))
|
||||
visibility = if (text.isNullOrBlank()) View.INVISIBLE else View.VISIBLE
|
||||
@@ -79,34 +84,58 @@ open class ContentRankingGridCardView @JvmOverloads constructor(
|
||||
currentItem?.let(::applyAccessState)
|
||||
}
|
||||
|
||||
private fun bindDelta(item: ContentRankingItem) {
|
||||
private fun bindDelta(
|
||||
item: ContentRankingItem,
|
||||
textStyle: ContentRankingTextStyle
|
||||
) {
|
||||
requireNotNull(deltaGroup).visibility = if (item.showRankChange) View.VISIBLE else View.GONE
|
||||
if (!item.showRankChange) return
|
||||
|
||||
val presentation = ContentRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
|
||||
applyDeltaContainer(presentation)
|
||||
val scale = RankingResponsiveScale.fromResources(resources)
|
||||
applyDeltaContainer(presentation, scale)
|
||||
requireNotNull(deltaIcon).apply {
|
||||
setImageResource(presentation.iconRes)
|
||||
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||
width = presentation.iconWidthDp.dpToPx()
|
||||
height = presentation.iconHeightDp.dpToPx()
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx()
|
||||
width = presentation.iconWidthDp.dpToPx(scale)
|
||||
height = presentation.iconHeightDp.dpToPx(scale)
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx(scale)
|
||||
}
|
||||
}
|
||||
requireNotNull(deltaAmountText).apply {
|
||||
text = presentation.amountText
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.deltaTextSizeSp)
|
||||
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyDeltaContainer(presentation: ContentRankingDeltaPresentation) {
|
||||
private fun applyDeltaContainer(
|
||||
presentation: ContentRankingDeltaPresentation,
|
||||
scale: Float
|
||||
) {
|
||||
requireNotNull(deltaGroup).apply {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyTextStyle(style: ContentRankingTextStyle) {
|
||||
requireNotNull(rankText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp)
|
||||
requireNotNull(titleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.titleTextSizeSp)
|
||||
requireNotNull(creatorText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.creatorTextSizeSp)
|
||||
requireNotNull(deltaAmountText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp)
|
||||
}
|
||||
|
||||
private fun defaultTextStyle(): ContentRankingTextStyle {
|
||||
val scale = RankingResponsiveScale.fromResources(resources)
|
||||
return if (this is ContentRankingSmallGridCardView) {
|
||||
ContentRankingTextStyle.smallGrid(scale)
|
||||
} else {
|
||||
ContentRankingTextStyle.mediumGrid(scale)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyAccessState(item: ContentRankingItem) {
|
||||
applyBlur(item.isInaccessible)
|
||||
isClickable = item.isTouchable && clickListener != null
|
||||
@@ -120,26 +149,32 @@ open class ContentRankingGridCardView @JvmOverloads constructor(
|
||||
|
||||
private fun positionMedium(size: ContentRankingCardSize) {
|
||||
val scale = size.widthPx / 185f
|
||||
val textStyle = ContentRankingTextStyle.mediumGrid(RankingResponsiveScale.fromResources(resources))
|
||||
currentTextStyle = textStyle
|
||||
requireNotNull(rankText).apply {
|
||||
textSize = 54f
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.rankTextSizeSp)
|
||||
layoutParams = LayoutParams((55 * scale).roundToInt(), (75 * scale).roundToInt())
|
||||
setPadding(0, 0, 0, (6 * scale).roundToInt())
|
||||
}
|
||||
requireNotNull(titleText).textSize = 22f
|
||||
requireNotNull(titleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.titleTextSizeSp)
|
||||
requireNotNull(creatorText).setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.creatorTextSizeSp)
|
||||
placeDelta(left = 10, top = 70, scale = scale)
|
||||
placeLabel(width = 165, top = 136, scale = scale, size = size)
|
||||
}
|
||||
|
||||
private fun positionSmall(size: ContentRankingCardSize) {
|
||||
val scale = size.widthPx / 122f
|
||||
val textStyle = ContentRankingTextStyle.smallGrid(RankingResponsiveScale.fromResources(resources))
|
||||
currentTextStyle = textStyle
|
||||
requireNotNull(rankText).apply {
|
||||
textSize = 40f
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.rankTextSizeSp)
|
||||
layoutParams = LayoutParams((42 * scale).roundToInt(), (56 * scale).roundToInt()).apply {
|
||||
leftMargin = (8 * scale).roundToInt()
|
||||
}
|
||||
setPadding(0, 0, 0, (5 * scale).roundToInt())
|
||||
}
|
||||
requireNotNull(titleText).textSize = 14f
|
||||
requireNotNull(titleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.titleTextSizeSp)
|
||||
requireNotNull(creatorText).setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.creatorTextSizeSp)
|
||||
placeDelta(left = 10, top = 49, scale = scale)
|
||||
placeLabel(width = 102, top = 81, scale = scale, size = size)
|
||||
}
|
||||
@@ -178,7 +213,7 @@ open class ContentRankingGridCardView @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 {
|
||||
const val SMALL_THRESHOLD_PX = 140
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewOutlineProvider
|
||||
@@ -13,6 +14,7 @@ import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScale
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ContentRankingHorizontalCardView @JvmOverloads constructor(
|
||||
@@ -48,11 +50,13 @@ class ContentRankingHorizontalCardView @JvmOverloads constructor(
|
||||
|
||||
fun bind(item: ContentRankingItem) {
|
||||
currentItem = item
|
||||
val textStyle = ContentRankingTextStyle.horizontal(RankingResponsiveScale.fromResources(resources))
|
||||
applyTextStyle(textStyle)
|
||||
requireNotNull(rankText).apply {
|
||||
text = item.rank.toString()
|
||||
applyContentRankingRankGradient()
|
||||
}
|
||||
bindDelta(item)
|
||||
bindDelta(item, textStyle)
|
||||
val inaccessibleMessage = context.getString(R.string.content_ranking_inaccessible_info)
|
||||
requireNotNull(titleText).text = item.displayContentName(inaccessibleMessage)
|
||||
requireNotNull(creatorText).text = item.displayCreatorName()
|
||||
@@ -69,6 +73,7 @@ class ContentRankingHorizontalCardView @JvmOverloads constructor(
|
||||
height = size.heightPx
|
||||
}
|
||||
positionViews(size)
|
||||
applyTextStyle(ContentRankingTextStyle.horizontal(RankingResponsiveScale.fromResources(resources)))
|
||||
}
|
||||
|
||||
fun imageView(): ImageView = requireNotNull(image)
|
||||
@@ -78,35 +83,51 @@ class ContentRankingHorizontalCardView @JvmOverloads constructor(
|
||||
currentItem?.let(::applyAccessState)
|
||||
}
|
||||
|
||||
private fun bindDelta(item: ContentRankingItem) {
|
||||
private fun bindDelta(
|
||||
item: ContentRankingItem,
|
||||
textStyle: ContentRankingTextStyle
|
||||
) {
|
||||
val deltaGroup = findViewById<View>(R.id.ll_content_ranking_delta)
|
||||
deltaGroup.visibility = if (item.showRankChange) View.VISIBLE else View.GONE
|
||||
if (!item.showRankChange) return
|
||||
|
||||
val presentation = ContentRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
|
||||
applyDeltaContainer(presentation)
|
||||
val scale = RankingResponsiveScale.fromResources(resources)
|
||||
applyDeltaContainer(presentation, scale)
|
||||
requireNotNull(deltaIcon).apply {
|
||||
setImageResource(presentation.iconRes)
|
||||
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||
width = presentation.iconWidthDp.dpToPx()
|
||||
height = presentation.iconHeightDp.dpToPx()
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx()
|
||||
width = presentation.iconWidthDp.dpToPx(scale)
|
||||
height = presentation.iconHeightDp.dpToPx(scale)
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx(scale)
|
||||
}
|
||||
}
|
||||
requireNotNull(deltaAmountText).apply {
|
||||
text = presentation.amountText
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.deltaTextSizeSp)
|
||||
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyDeltaContainer(presentation: ContentRankingDeltaPresentation) {
|
||||
private fun applyDeltaContainer(
|
||||
presentation: ContentRankingDeltaPresentation,
|
||||
scale: Float
|
||||
) {
|
||||
findViewById<View>(R.id.ll_content_ranking_delta).apply {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyTextStyle(style: ContentRankingTextStyle) {
|
||||
requireNotNull(rankText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp)
|
||||
requireNotNull(titleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.titleTextSizeSp)
|
||||
requireNotNull(creatorText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.creatorTextSizeSp)
|
||||
requireNotNull(inaccessibleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.titleTextSizeSp)
|
||||
requireNotNull(deltaAmountText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp)
|
||||
}
|
||||
|
||||
private fun applyAccessState(item: ContentRankingItem) {
|
||||
applyBlur(item.isInaccessible)
|
||||
isClickable = item.isTouchable && clickListener != null
|
||||
@@ -157,5 +178,5 @@ class ContentRankingHorizontalCardView @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()
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewOutlineProvider
|
||||
@@ -13,6 +14,7 @@ import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingResponsiveScale
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ContentRankingLargeCardView @JvmOverloads constructor(
|
||||
@@ -50,11 +52,13 @@ class ContentRankingLargeCardView @JvmOverloads constructor(
|
||||
|
||||
fun bind(item: ContentRankingItem) {
|
||||
currentItem = item
|
||||
val textStyle = ContentRankingTextStyle.large(RankingResponsiveScale.fromResources(resources))
|
||||
applyTextStyle(textStyle)
|
||||
requireNotNull(rankText).apply {
|
||||
text = item.rank.toString()
|
||||
applyContentRankingRankGradient()
|
||||
}
|
||||
bindDelta(item)
|
||||
bindDelta(item, textStyle)
|
||||
requireNotNull(titleText).apply {
|
||||
text = item.displayContentName(context.getString(R.string.content_ranking_inaccessible_info))
|
||||
visibility = if (text.isNullOrBlank()) View.INVISIBLE else View.VISIBLE
|
||||
@@ -72,6 +76,7 @@ class ContentRankingLargeCardView @JvmOverloads constructor(
|
||||
height = size.heightPx
|
||||
}
|
||||
positionViews(size)
|
||||
applyTextStyle(ContentRankingTextStyle.large(RankingResponsiveScale.fromResources(resources)))
|
||||
}
|
||||
|
||||
fun imageView(): ImageView = contentImageView()
|
||||
@@ -83,34 +88,49 @@ class ContentRankingLargeCardView @JvmOverloads constructor(
|
||||
currentItem?.let(::applyAccessState)
|
||||
}
|
||||
|
||||
private fun bindDelta(item: ContentRankingItem) {
|
||||
private fun bindDelta(
|
||||
item: ContentRankingItem,
|
||||
textStyle: ContentRankingTextStyle
|
||||
) {
|
||||
requireNotNull(deltaGroup).visibility = if (item.showRankChange) View.VISIBLE else View.GONE
|
||||
if (!item.showRankChange) return
|
||||
|
||||
val presentation = ContentRankingDeltaPresentation.from(item.rankChangeType, item.rankChangeAmount)
|
||||
applyDeltaContainer(presentation)
|
||||
val scale = RankingResponsiveScale.fromResources(resources)
|
||||
applyDeltaContainer(presentation, scale)
|
||||
requireNotNull(deltaIcon).apply {
|
||||
setImageResource(presentation.iconRes)
|
||||
layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||
width = presentation.iconWidthDp.dpToPx()
|
||||
height = presentation.iconHeightDp.dpToPx()
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx()
|
||||
width = presentation.iconWidthDp.dpToPx(scale)
|
||||
height = presentation.iconHeightDp.dpToPx(scale)
|
||||
marginStart = presentation.iconMarginStartDp.dpToPx(scale)
|
||||
}
|
||||
}
|
||||
requireNotNull(deltaAmountText).apply {
|
||||
text = presentation.amountText
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, textStyle.deltaTextSizeSp)
|
||||
visibility = if (presentation.showAmount) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyDeltaContainer(presentation: ContentRankingDeltaPresentation) {
|
||||
private fun applyDeltaContainer(
|
||||
presentation: ContentRankingDeltaPresentation,
|
||||
scale: Float
|
||||
) {
|
||||
requireNotNull(deltaGroup).apply {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyTextStyle(style: ContentRankingTextStyle) {
|
||||
requireNotNull(rankText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.rankTextSizeSp)
|
||||
requireNotNull(titleText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.titleTextSizeSp)
|
||||
requireNotNull(creatorText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.creatorTextSizeSp)
|
||||
requireNotNull(deltaAmountText).setTextSize(TypedValue.COMPLEX_UNIT_SP, style.deltaTextSizeSp)
|
||||
}
|
||||
|
||||
private fun applyAccessState(item: ContentRankingItem) {
|
||||
applyBlur(item.isInaccessible)
|
||||
isClickable = item.isTouchable && clickListener != null
|
||||
@@ -159,7 +179,7 @@ class ContentRankingLargeCardView @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 {
|
||||
const val FIGMA_WIDTH = 374
|
||||
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.v2.widget.contentranking
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -144,6 +145,83 @@ class ContentRankingCardViewTest {
|
||||
assertEquals(View.VISIBLE, view.findViewById<View>(R.id.iv_content_ranking_background).visibility)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `large card는 402dp 미만에서 실제 text size를 축소한다`() {
|
||||
val view = inflateView<ContentRankingLargeCardView>(
|
||||
layoutResId = R.layout.view_content_ranking_large_card,
|
||||
screenWidthDp = 360
|
||||
)
|
||||
|
||||
view.bind(sampleItem(rank = 1))
|
||||
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_rank), 96f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_title), 22f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_creator), 12f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_delta_amount), 16f * 360f / 402f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `medium grid card는 402dp 미만에서 실제 text size를 축소한다`() {
|
||||
val view = inflateView<ContentRankingMediumGridCardView>(
|
||||
layoutResId = R.layout.view_content_ranking_medium_grid_card,
|
||||
screenWidthDp = 360
|
||||
)
|
||||
|
||||
view.setCardSize(ContentRankingCardSize(widthPx = 185, heightPx = 185))
|
||||
view.bind(sampleItem(rank = 2))
|
||||
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_rank), 54f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_title), 22f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_creator), 12f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_delta_amount), 16f * 360f / 402f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `small grid card는 402dp 미만에서 조건부 baseline text size를 축소한다`() {
|
||||
val view = inflateView<ContentRankingSmallGridCardView>(
|
||||
layoutResId = R.layout.view_content_ranking_small_grid_card,
|
||||
screenWidthDp = 360
|
||||
)
|
||||
|
||||
view.setCardSize(ContentRankingCardSize(widthPx = 122, heightPx = 122))
|
||||
view.bind(sampleItem(rank = 8))
|
||||
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_rank), 36f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_title), 14f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_creator), 12f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_delta_amount), 16f * 360f / 402f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `small grid card는 card size 적용 전 bind에서도 402dp 미만 text size를 축소한다`() {
|
||||
val view = inflateView<ContentRankingSmallGridCardView>(
|
||||
layoutResId = R.layout.view_content_ranking_small_grid_card,
|
||||
screenWidthDp = 360
|
||||
)
|
||||
|
||||
view.bind(sampleItem(rank = 8))
|
||||
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_rank), 36f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_title), 14f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_creator), 12f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_delta_amount), 16f * 360f / 402f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `horizontal card는 402dp 미만에서 실제 text size를 축소한다`() {
|
||||
val view = inflateView<ContentRankingHorizontalCardView>(
|
||||
layoutResId = R.layout.view_content_ranking_horizontal_card,
|
||||
screenWidthDp = 360
|
||||
)
|
||||
|
||||
view.bind(sampleItem(rank = 11))
|
||||
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_rank), 40f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_title), 18f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_creator), 14f * 360f / 402f)
|
||||
assertTextSizeSp(view.findViewById(R.id.tv_content_ranking_delta_amount), 16f * 360f / 402f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `large view holder는 배경 blur와 전경 non blur coverImage를 모두 로드한다`() {
|
||||
val source = projectFile(
|
||||
@@ -161,11 +239,28 @@ class ContentRankingCardViewTest {
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun <reified T : View> inflateView(layoutResId: Int): T {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
private inline fun <reified T : View> inflateView(
|
||||
layoutResId: Int,
|
||||
screenWidthDp: Int? = null
|
||||
): T {
|
||||
val baseContext = ApplicationProvider.getApplicationContext<Context>()
|
||||
val context = if (screenWidthDp == null) {
|
||||
baseContext
|
||||
} else {
|
||||
baseContext.createConfigurationContext(
|
||||
Configuration(baseContext.resources.configuration).apply { this.screenWidthDp = screenWidthDp }
|
||||
)
|
||||
}
|
||||
return LayoutInflater.from(context).inflate(layoutResId, null, false) as T
|
||||
}
|
||||
|
||||
private fun assertTextSizeSp(
|
||||
view: TextView,
|
||||
expectedSp: Float
|
||||
) {
|
||||
assertEquals(expectedSp, view.textSize / view.resources.displayMetrics.scaledDensity, 0.0001f)
|
||||
}
|
||||
|
||||
private fun assertRankTextBox(
|
||||
view: TextView,
|
||||
expectedWidth: Int,
|
||||
|
||||
Reference in New Issue
Block a user