feat(home): 응원 크리에이터 카드 바인딩을 추가한다
This commit is contained in:
@@ -30,7 +30,6 @@ import kr.co.vividnext.sodalive.v2.main.home.ui.HomeAiCharacterAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeBannerBinder
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeCheerCreatorAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFirstAudioAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFollowAllButtonBinder
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeGenreCreatorAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeLiveAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeRecentActivityCreatorAdapter
|
||||
@@ -47,7 +46,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||
private val firstAudioAdapter = HomeFirstAudioAdapter()
|
||||
private val aiCharacterAdapter = HomeAiCharacterAdapter()
|
||||
private val genreCreatorAdapter = HomeGenreCreatorAdapter { creatorIds -> onGenreFollowAllClick(creatorIds) }
|
||||
private val cheerCreatorAdapter = HomeCheerCreatorAdapter()
|
||||
private val cheerCreatorAdapter = HomeCheerCreatorAdapter { creatorIds -> onCheerFollowAllClick(creatorIds) }
|
||||
private var bannerBinder: HomeBannerBinder? = null
|
||||
private var onGenreFollowAllClick: (List<Long>) -> Unit = {}
|
||||
private var onCheerFollowAllClick: (List<Long>) -> Unit = {}
|
||||
@@ -135,13 +134,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||
|
||||
private fun bindCheerCreatorSection(section: HomeRecommendationCheerCreatorSection) {
|
||||
binding.llHomeCheerCreatorSection.visibility = section.items.toSectionVisibility()
|
||||
cheerCreatorAdapter.submitItems(section.items)
|
||||
HomeFollowAllButtonBinder.bind(
|
||||
view = binding.viewHomeCheerFollowAll.root,
|
||||
creatorIds = section.items.map { it.creatorId },
|
||||
isFollowCompleted = section.isFollowCompleted,
|
||||
onClick = onCheerFollowAllClick
|
||||
)
|
||||
cheerCreatorAdapter.submitSection(section.items, section.isFollowCompleted)
|
||||
}
|
||||
|
||||
private fun bindPopularCommunitySection(section: HomeRecommendationPopularCommunityPostSection) {
|
||||
@@ -247,7 +240,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||
HomeRecommendationGenreCreatorGroupUiModel("판타지", sampleCreators(701L, count = 8))
|
||||
)
|
||||
),
|
||||
cheerCreators = HomeRecommendationCheerCreatorSection(sampleCreators(701L)),
|
||||
cheerCreators = HomeRecommendationCheerCreatorSection(sampleCreators(701L, count = 8)),
|
||||
popularCommunityPosts = HomeRecommendationPopularCommunityPostSection(emptyList())
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,136 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.ui
|
||||
|
||||
class HomeCheerCreatorAdapter : HomeCreatorProfileAdapter()
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.GridLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.extensions.loadUrl
|
||||
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationCreatorUiModel
|
||||
|
||||
class HomeCheerCreatorAdapter(
|
||||
private val onFollowAllClick: (List<Long>) -> Unit
|
||||
) : RecyclerView.Adapter<HomeCheerCreatorAdapter.CheerCreatorGroupViewHolder>() {
|
||||
private var creators: List<HomeRecommendationCreatorUiModel> = emptyList()
|
||||
private var isFollowCompleted: Boolean = false
|
||||
|
||||
fun submitSection(
|
||||
creators: List<HomeRecommendationCreatorUiModel>,
|
||||
isFollowCompleted: Boolean
|
||||
) {
|
||||
this.creators = creators
|
||||
this.isFollowCompleted = isFollowCompleted
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheerCreatorGroupViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_cheer_creator_group, parent, false)
|
||||
view.layoutParams = cheerGroupLayoutParams(parent)
|
||||
return CheerCreatorGroupViewHolder(view, parent, onFollowAllClick)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CheerCreatorGroupViewHolder, position: Int) {
|
||||
holder.bind(creators, isFollowCompleted)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (creators.isEmpty()) 0 else 1
|
||||
|
||||
class CheerCreatorGroupViewHolder(
|
||||
itemView: View,
|
||||
private val parent: ViewGroup,
|
||||
private val onFollowAllClick: (List<Long>) -> Unit
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
private val creatorGrid = itemView.findViewById<GridLayout>(R.id.gl_home_cheer_creator_profiles)
|
||||
private val followAllButton = itemView.findViewById<View>(R.id.view_home_cheer_group_follow_all)
|
||||
|
||||
fun bind(creators: List<HomeRecommendationCreatorUiModel>, isFollowCompleted: Boolean) {
|
||||
val visibleCreators = creators.take(CREATOR_COUNT_PER_GROUP)
|
||||
bindCreators(visibleCreators, calculateProfileSize())
|
||||
creatorGrid.post {
|
||||
bindCreators(visibleCreators, calculateProfileSize())
|
||||
}
|
||||
HomeFollowAllButtonBinder.bind(
|
||||
view = followAllButton,
|
||||
creatorIds = creators.map { it.creatorId },
|
||||
isFollowCompleted = isFollowCompleted,
|
||||
onClick = onFollowAllClick
|
||||
)
|
||||
}
|
||||
|
||||
private fun calculateProfileSize(): Int {
|
||||
val gridWidth = creatorGrid.width.takeIf { it > 0 }
|
||||
?: (resolvedCardWidth() - itemView.paddingStart - itemView.paddingEnd)
|
||||
val totalColumnGap = itemView.resources.getDimensionPixelSize(R.dimen.spacing_14) * (GRID_COLUMN_COUNT - 1)
|
||||
return (gridWidth - totalColumnGap) / GRID_COLUMN_COUNT
|
||||
}
|
||||
|
||||
private fun resolvedCardWidth(): Int {
|
||||
val parentContentWidth = parentContentWidth()
|
||||
itemView.width.takeIf { it > 0 }?.let { return minOf(it, parentContentWidth) }
|
||||
itemView.layoutParams.width.takeIf { it > 0 }?.let { return minOf(it, parentContentWidth) }
|
||||
|
||||
parentContentWidth.takeIf { it > 0 }?.let { return it }
|
||||
|
||||
return itemView.resources.displayMetrics.widthPixels - parentHorizontalInset()
|
||||
}
|
||||
|
||||
private fun parentContentWidth(): Int {
|
||||
return parent.width - parentHorizontalInset()
|
||||
}
|
||||
|
||||
private fun parentHorizontalInset(): Int {
|
||||
val paddingInset = parent.paddingStart + parent.paddingEnd
|
||||
return paddingInset.takeIf { it > 0 } ?: itemView.resources.getDimensionPixelSize(R.dimen.spacing_28)
|
||||
}
|
||||
|
||||
private fun bindCreators(creators: List<HomeRecommendationCreatorUiModel>, profileSize: Int) {
|
||||
creatorGrid.removeAllViews()
|
||||
creators.forEachIndexed { index, creator ->
|
||||
val profileView = LayoutInflater.from(creatorGrid.context).inflate(
|
||||
R.layout.item_home_genre_creator_profile,
|
||||
creatorGrid,
|
||||
false
|
||||
)
|
||||
val row = index / GRID_COLUMN_COUNT
|
||||
val column = index % GRID_COLUMN_COUNT
|
||||
profileView.layoutParams = GridLayout.LayoutParams(
|
||||
GridLayout.spec(row),
|
||||
GridLayout.spec(column)
|
||||
).apply {
|
||||
width = profileSize
|
||||
height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
if (column < GRID_COLUMN_COUNT - 1) {
|
||||
marginEnd = profileView.resources.getDimensionPixelSize(R.dimen.spacing_14)
|
||||
}
|
||||
if (row > 0) {
|
||||
topMargin = profileView.resources.getDimensionPixelSize(R.dimen.spacing_14)
|
||||
}
|
||||
}
|
||||
profileView.findViewById<ImageView>(R.id.iv_home_genre_creator_profile).apply {
|
||||
if (creator.profileImage == null) {
|
||||
setImageDrawable(null)
|
||||
} else {
|
||||
loadUrl(creator.profileImage)
|
||||
}
|
||||
}
|
||||
profileView.findViewById<TextView>(R.id.tv_home_genre_creator_profile_nickname).text = creator.nickname
|
||||
creatorGrid.addView(profileView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CREATOR_COUNT_PER_GROUP = 8
|
||||
private const val GRID_COLUMN_COUNT = 4
|
||||
}
|
||||
}
|
||||
|
||||
private fun cheerGroupLayoutParams(parent: ViewGroup): RecyclerView.LayoutParams {
|
||||
val paddingInset = parent.paddingStart + parent.paddingEnd
|
||||
val horizontalInset = paddingInset.takeIf { it > 0 } ?: parent.resources.getDimensionPixelSize(R.dimen.spacing_28)
|
||||
val width = (parent.width - horizontalInset).takeIf { it > 0 } ?: ViewGroup.LayoutParams.MATCH_PARENT
|
||||
return RecyclerView.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
@@ -189,14 +189,10 @@
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_home_cheer_creators"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="@dimen/spacing_20"
|
||||
android:paddingHorizontal="@dimen/spacing_14"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
|
||||
<include
|
||||
android:id="@+id/view_home_cheer_follow_all"
|
||||
layout="@layout/view_home_follow_all_button" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
Reference in New Issue
Block a user