fix(feed): 커뮤니티 이미지 원본비율 높이를 적용한다

This commit is contained in:
2026-07-12 20:51:30 +09:00
parent 79eadbd39d
commit 9244a00713
5 changed files with 94 additions and 7 deletions

View File

@@ -0,0 +1,12 @@
package kr.co.vividnext.sodalive.v2.widget.feed
import kotlin.math.roundToInt
fun calculateFeedCommunityImageHeight(
containerWidthPx: Int,
intrinsicWidthPx: Int,
intrinsicHeightPx: Int
): Int? {
if (containerWidthPx <= 0 || intrinsicWidthPx <= 0 || intrinsicHeightPx <= 0) return null
return (containerWidthPx * intrinsicHeightPx.toFloat() / intrinsicWidthPx).roundToInt()
}

View File

@@ -62,6 +62,7 @@ class FeedCommunityView @JvmOverloads constructor(
val isLocked = item.price > 0 && !item.existOrdered
val hasImage = !item.imageUrl.isNullOrBlank()
requireNotNull(communityImageContainer).isVisible = hasImage || isLocked
resetCommunityImageHeight()
requireNotNull(communityImage).isVisible = hasImage
if (!hasImage || isLocked) {
requireNotNull(communityImage).setImageDrawable(null)
@@ -79,6 +80,33 @@ class FeedCommunityView @JvmOverloads constructor(
fun boundItem(): FeedItem.Community? = currentItem
fun applyCommunityImageSize(
intrinsicWidthPx: Int,
intrinsicHeightPx: Int
) {
val container = requireNotNull(communityImageContainer)
val width = container.width.takeIf { it > 0 }
?: container.measuredWidth.takeIf { it > 0 }
?: (width - paddingLeft - paddingRight).takeIf { it > 0 }
?: run {
post { applyCommunityImageSize(intrinsicWidthPx, intrinsicHeightPx) }
return
}
val imageHeight = calculateFeedCommunityImageHeight(
containerWidthPx = width,
intrinsicWidthPx = intrinsicWidthPx,
intrinsicHeightPx = intrinsicHeightPx
) ?: return
container.layoutParams = container.layoutParams.apply { height = imageHeight }
}
private fun resetCommunityImageHeight() {
val container = requireNotNull(communityImageContainer)
container.layoutParams = container.layoutParams.apply {
height = DEFAULT_IMAGE_HEIGHT_DP.dpToPx()
}
}
fun setFeedSize(size: FeedSize) {
updateRootWidth(size.rootWidthDp.dpToPx())
}
@@ -128,5 +156,6 @@ class FeedCommunityView @JvmOverloads constructor(
private companion object {
const val CARD_RADIUS_DP = 14
const val COMMUNITY_IMAGE_RADIUS_DP = 14
const val DEFAULT_IMAGE_HEIGHT_DP = 236
}
}

View File

@@ -67,8 +67,9 @@
<FrameLayout
android:id="@+id/fl_feed_community_image_container"
android:layout_width="match_parent"
android:layout_height="236dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_14"
android:background="@drawable/bg_feed_community_image"
android:visibility="gone"
tools:visibility="visible">
@@ -76,9 +77,8 @@
android:id="@+id/iv_feed_community_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_feed_community_image"
android:contentDescription="@string/a11y_feed_content_image"
android:scaleType="centerCrop"
android:scaleType="fitCenter"
tools:src="@drawable/ic_launcher_background" />
<LinearLayout

View File

@@ -0,0 +1,41 @@
package kr.co.vividnext.sodalive.v2.widget.feed
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
class FeedCommunityImageSizeTest {
@Test
fun `커뮤니티 이미지는 원본 비율로 높이를 계산한다`() {
val height = calculateFeedCommunityImageHeight(
containerWidthPx = 300,
intrinsicWidthPx = 1200,
intrinsicHeightPx = 800
)
assertEquals(200, height)
}
@Test
fun `커뮤니티 이미지는 특정 최대 높이로 제한하지 않는다`() {
val height = calculateFeedCommunityImageHeight(
containerWidthPx = 300,
intrinsicWidthPx = 600,
intrinsicHeightPx = 1800
)
assertEquals(900, height)
}
@Test
fun `커뮤니티 이미지는 크기 정보가 없으면 높이를 계산하지 않는다`() {
val height = calculateFeedCommunityImageHeight(
containerWidthPx = 300,
intrinsicWidthPx = 0,
intrinsicHeightPx = 800
)
assertNull(height)
}
}

View File

@@ -85,14 +85,15 @@ class FeedViewTest {
}
@Test
fun `community layout matches creator channel feed row structure`() {
fun `community layout uses runtime image height instead of fixed crop height`() {
val view = inflateView<FeedCommunityView>(R.layout.view_feed_community)
val layout = projectFile("app/src/main/res/layout/view_feed_community.xml").readText()
assertFalse(layout.contains("@+id/tv_feed_community_keyword"))
assertTrue(layout.contains("android:layout_width=\"match_parent\""))
assertTrue(layout.contains("android:maxLines=\"5\""))
assertTrue(layout.contains("android:layout_height=\"236dp\""))
assertFalse(layout.contains("android:layout_height=\"236dp\""))
assertTrue(layout.contains("android:scaleType=\"fitCenter\""))
assertTrue(layout.contains("@drawable/bg_creator_channel_community_price"))
assertTrue(layout.contains("@drawable/ic_bar_cash"))
assertFalse(layout.contains("android:drawableStart=\"@drawable/ic_bar_cash\""))
@@ -152,17 +153,21 @@ class FeedViewTest {
}
@Test
fun `community image container keeps creator channel fixed height`() {
fun `community image container keeps fallback height until original image ratio is applied`() {
val view = inflateView<FeedCommunityView>(R.layout.view_feed_community)
val imageContainer = view.findViewById<FrameLayout>(R.id.fl_feed_community_image_container)
view.bind(sampleCommunityItem(bodyText = "본문", keywordText = "", imageUrl = "https://example.com/post.png"))
view.measure(exactly(402.dpToPx()), View.MeasureSpec.UNSPECIFIED)
assertEquals(236.dpToPx(), imageContainer.measuredHeight)
view.applyCommunityImageSize(intrinsicWidthPx = 600, intrinsicHeightPx = 1800)
view.measure(exactly(402.dpToPx()), View.MeasureSpec.UNSPECIFIED)
val expectedImageWidth = 402.dpToPx() - view.paddingLeft - view.paddingRight
assertEquals(expectedImageWidth, imageContainer.measuredWidth)
assertEquals(236.dpToPx(), imageContainer.measuredHeight)
assertEquals(expectedImageWidth * 3, imageContainer.measuredHeight)
assertEquals(true, imageContainer.clipToOutline)
assertNotNull(imageContainer.outlineProvider)
}