diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/ui/CreatorChannelDonationAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/ui/CreatorChannelDonationAdapter.kt index 4592f920..4663ee8a 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/ui/CreatorChannelDonationAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/ui/CreatorChannelDonationAdapter.kt @@ -1,6 +1,9 @@ package kr.co.vividnext.sodalive.v2.creator.channel.donation.ui +import android.content.Context +import android.graphics.Rect import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -65,6 +68,9 @@ class CreatorChannelDonationAdapter( init { binding.rvCreatorChannelDonationRankingMembers.layoutManager = GridLayoutManager(itemView.context, 4) + binding.rvCreatorChannelDonationRankingMembers.addItemDecoration( + CreatorChannelDonationRankingItemDecoration(itemView.context, spanCount = 4) + ) binding.rvCreatorChannelDonationRankingMembers.adapter = rankingAdapter binding.btnCreatorChannelDonationRankingAll.setOnClickListener { onRankingAllClick() } } @@ -106,3 +112,21 @@ private sealed interface CreatorChannelDonationListItem { data class Ranking(val rankings: List) : CreatorChannelDonationListItem data class Donation(val donation: CreatorChannelDonationUiModel) : CreatorChannelDonationListItem } + +private class CreatorChannelDonationRankingItemDecoration( + context: Context, + private val spanCount: Int +) : RecyclerView.ItemDecoration() { + + private val spacing: Int = (14 * context.resources.displayMetrics.density).toInt() + + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + val position = parent.getChildAdapterPosition(view) + if (position == RecyclerView.NO_POSITION) return + + val column = position % spanCount + outRect.left = column * spacing / spanCount + outRect.right = spacing - (column + 1) * spacing / spanCount + outRect.top = if (position >= spanCount) spacing else 0 + } +} diff --git a/app/src/main/res/layout/item_creator_channel_donation_ranking_member.xml b/app/src/main/res/layout/item_creator_channel_donation_ranking_member.xml index 082e4e70..865dc691 100644 --- a/app/src/main/res/layout/item_creator_channel_donation_ranking_member.xml +++ b/app/src/main/res/layout/item_creator_channel_donation_ranking_member.xml @@ -1,48 +1,73 @@ - + android:clipChildren="false"> - + + + - + - + diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/CreatorChannelDonationFragmentLayoutTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/CreatorChannelDonationFragmentLayoutTest.kt index 671fcfd8..a3b05934 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/CreatorChannelDonationFragmentLayoutTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/CreatorChannelDonationFragmentLayoutTest.kt @@ -34,7 +34,6 @@ class CreatorChannelDonationFragmentLayoutTest { val emptyDonationButton = requireNotNull(root.findViewById(R.id.btn_creator_channel_donation_empty_write)) val errorMessage = requireNotNull(root.findViewById(R.id.tv_creator_channel_donation_error_message)) val retryButton = requireNotNull(root.findViewById(R.id.btn_creator_channel_donation_retry)) - val donationButton = requireNotNull(root.findViewById(R.id.btn_creator_channel_donation_write)) assertSame(root, countBar.parent) assertSame(root, donationList.parent) @@ -43,9 +42,9 @@ class CreatorChannelDonationFragmentLayoutTest { assertSame(emptyContainer, emptyDonationButton.parent) assertSame(root, errorMessage.parent) assertSame(root, retryButton.parent) - assertSame(root, donationButton.parent) assertTrue(layout.contains("android:background=\"@color/black\"")) assertTrue(layout.contains("tools:listitem=\"@layout/item_creator_channel_donation\"")) + assertTrue(!layout.contains("btn_creator_channel_donation_write")) assertTrue(!layout.contains("creator_channel_donation_sort")) } @@ -89,6 +88,9 @@ class CreatorChannelDonationFragmentLayoutTest { fun `후원 ranking item layout은 타이틀 grid 전체보기 button을 제공한다`() { val item = inflateView(R.layout.item_creator_channel_donation_ranking) val layout = projectFile("app/src/main/res/layout/item_creator_channel_donation_ranking.xml").readText() + val adapter = projectFile( + "app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/donation/ui/CreatorChannelDonationAdapter.kt" + ).readText() assertNotNull(item.findViewById(R.id.tv_creator_channel_donation_ranking_title)) assertNotNull(item.findViewById(R.id.rv_creator_channel_donation_ranking_members)) @@ -97,15 +99,40 @@ class CreatorChannelDonationFragmentLayoutTest { assertTrue(layout.contains("android:text=\"@string/creator_channel_donation_ranking_all\"")) assertTrue(layout.contains("android:layout_marginHorizontal=\"@dimen/spacing_14\"")) assertTrue(layout.contains("android:background=\"@drawable/bg_creator_channel_donation_card\"")) + assertTrue(layout.contains("android:layout_width=\"match_parent\"")) + assertTrue(adapter.contains("GridLayoutManager(itemView.context, 4)")) + assertTrue(adapter.contains("CreatorChannelDonationRankingItemDecoration(itemView.context, spanCount = 4)")) + assertTrue(adapter.contains("column * spacing / spanCount")) + assertTrue(adapter.contains("spacing - (column + 1) * spacing / spanCount")) } @Test fun `후원 ranking member item layout은 프로필 닉네임 rank overlay를 제공한다`() { val item = inflateView(R.layout.item_creator_channel_donation_ranking_member) + val layout = projectFile("app/src/main/res/layout/item_creator_channel_donation_ranking_member.xml").readText() assertNotNull(item.findViewById(R.id.iv_creator_channel_donation_ranking_profile)) assertNotNull(item.findViewById(R.id.tv_creator_channel_donation_ranking_rank)) assertNotNull(item.findViewById(R.id.tv_creator_channel_donation_ranking_nickname)) + assertTrue(layout.contains("@+id/layout_creator_channel_donation_ranking_profile")) + assertTrue(layout.contains("android:clipChildren=\"false\"")) + assertTrue(layout.contains("app:layout_constraintDimensionRatio=\"1:1\"")) + assertTrue(layout.contains("android:layout_marginTop=\"6dp\"")) + assertTrue(layout.contains("android:fontFamily=\"@font/pattaya_regular\"")) + assertTrue(layout.contains("android:textSize=\"28sp\"")) + assertTrue(layout.contains("app:layout_constraintGuide_percent=\"0.63\"")) + assertTrue( + layout.contains( + "app:layout_constraintTop_toTopOf=\"@id/guideline_creator_channel_donation_ranking_rank_top\"" + ) + ) + assertTrue( + !layout.contains( + "app:layout_constraintBottom_toBottomOf=\"@id/iv_creator_channel_donation_ranking_profile\"" + ) + ) + assertTrue(!layout.contains("android:translationY=\"@dimen/spacing_8\"")) + assertTrue(!layout.contains("android:paddingBottom=\"@dimen/spacing_4\"")) } @Test