From 595bc50cde7f5b764940b97064f08638fba70158 Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 26 Jun 2026 15:42:38 +0900 Subject: [PATCH] =?UTF-8?q?fix(home):=20=ED=8C=94=EB=A1=9C=EC=9E=89=20?= =?UTF-8?q?=ED=83=AD=20=ED=9B=84=EC=86=8D=20UI=EB=A5=BC=20=EB=B3=B4?= =?UTF-8?q?=EC=A0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/v2/main/home/HomeMainFragment.kt | 15 +- .../main/home/ui/HomeFollowingChatAdapter.kt | 7 +- .../main/home/ui/HomeFollowingNewsAdapter.kt | 144 +++++++++++++----- .../main/res/layout/fragment_v2_main_home.xml | 7 +- .../res/layout/item_home_following_chat.xml | 81 ++++++---- .../layout/item_home_following_creator.xml | 8 +- 6 files changed, 167 insertions(+), 95 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt index 1b2e3ac2..c9a6b223 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt @@ -196,7 +196,7 @@ class HomeMainFragment : BaseFragment( adapter = followingLiveAdapter } binding.rvHomeFollowingRecentChats.apply { - layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) adapter = followingChatAdapter } binding.rvHomeFollowingMonthlySchedules.apply { @@ -448,10 +448,6 @@ class HomeMainFragment : BaseFragment( binding.viewHomePopularCommunityTitle.setTitle( R.string.home_recommendation_section_popular_community_posts ) - binding.viewHomeFollowingCreatorsTitle.setTitle( - R.string.screen_home_following_creators_title, - showMore = true - ) binding.viewHomeFollowingOnAirTitle.setTitle( R.string.screen_home_following_on_air, showMore = true @@ -465,12 +461,8 @@ class HomeMainFragment : BaseFragment( showMore = true ) binding.viewHomeFollowingRecentNewsTitle.setTitle( - R.string.screen_home_following_recent_news_title, - showMore = true + R.string.screen_home_following_recent_news_title ) - binding.viewHomeFollowingCreatorsTitle.ivSectionTitleChevron.setOnClickListener { - onFollowingSectionMoreClick(HomeFollowingSection.CREATORS) - } binding.viewHomeFollowingOnAirTitle.ivSectionTitleChevron.setOnClickListener { onFollowingSectionMoreClick(HomeFollowingSection.ON_AIR) } @@ -480,9 +472,6 @@ class HomeMainFragment : BaseFragment( binding.viewHomeFollowingMonthlySchedulesTitle.ivSectionTitleChevron.setOnClickListener { onFollowingSectionMoreClick(HomeFollowingSection.MONTHLY_SCHEDULES) } - binding.viewHomeFollowingRecentNewsTitle.ivSectionTitleChevron.setOnClickListener { - onFollowingSectionMoreClick(HomeFollowingSection.RECENT_NEWS) - } } private fun ViewSectionTitleBinding.setTitle( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt index 53bdcb0f..fc7c7176 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt @@ -22,10 +22,7 @@ class HomeFollowingChatAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_following_chat, parent, false) - view.layoutParams = RecyclerView.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { bottomMargin = parent.resources.getDimensionPixelSize(R.dimen.spacing_8) } + view.layoutParams = recyclerItemLayoutParams(parent) return ChatViewHolder(view, onClickItem) } @@ -43,12 +40,14 @@ class HomeFollowingChatAdapter( private val nicknameText = itemView.findViewById(R.id.tv_home_following_chat_creator_nickname) private val messageText = itemView.findViewById(R.id.tv_home_following_chat_message) private val timeText = itemView.findViewById(R.id.tv_home_following_chat_time) + private val directBadgeText = itemView.findViewById(R.id.tv_home_following_chat_direct_badge) fun bind(item: ChatRoomListUiItem) { profileImage.loadHomeCreatorProfileImage(item.targetImageUrl) nicknameText.text = item.targetName messageText.text = item.lastMessage timeText.text = formatChatRoomLastMessageTime(itemView.context, item.lastMessageAt) + directBadgeText.visibility = if (item.showDirectBadge) View.VISIBLE else View.GONE itemView.setOnClickListener { onClickItem(item) } } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt index 7c7466e5..64eaf57b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt @@ -3,13 +3,19 @@ package kr.co.vividnext.sodalive.v2.main.home.ui import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView -import androidx.core.view.isVisible 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.data.FollowingNewsType import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingNewsUiItem +import kr.co.vividnext.sodalive.v2.widget.feed.FeedContentView +import kr.co.vividnext.sodalive.v2.widget.feed.FeedItem +import kr.co.vividnext.sodalive.v2.widget.feed.FeedRankView +import kr.co.vividnext.sodalive.v2.widget.feed.FeedSize +import kr.co.vividnext.sodalive.v2.widget.feed.FeedVariant +import kr.co.vividnext.sodalive.v2.widget.feed.FeedWidthMode +import kr.co.vividnext.sodalive.v2.widget.feed.FeedCommunityView +import kotlin.math.roundToInt class HomeFollowingNewsAdapter( private val onClickItem: (HomeFollowingNewsUiItem) -> Unit = {} @@ -21,26 +27,34 @@ class HomeFollowingNewsAdapter( notifyDataSetChanged() } - override fun getItemViewType(position: Int): Int = when (items[position]) { + override fun getItemViewType(position: Int): Int = when (val item = items[position]) { is HomeFollowingNewsUiItem.Ranking -> VIEW_TYPE_RANKING - is HomeFollowingNewsUiItem.Content -> VIEW_TYPE_CONTENT + is HomeFollowingNewsUiItem.Content -> when (item.type) { + FollowingNewsType.COMMUNITY_POST -> VIEW_TYPE_COMMUNITY + FollowingNewsType.AUDIO_CONTENT, + FollowingNewsType.PHOTO_CONTENT -> VIEW_TYPE_CONTENT + FollowingNewsType.CREATOR_RANKING, + FollowingNewsType.CONTENT_RANKING -> VIEW_TYPE_CONTENT + } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder { - val layoutResId = if (viewType == VIEW_TYPE_RANKING) { - R.layout.item_home_following_news_rank - } else { - R.layout.item_home_following_news_content + val layoutResId = when (viewType) { + VIEW_TYPE_RANKING -> R.layout.view_feed_rank + VIEW_TYPE_COMMUNITY -> R.layout.view_feed_community + VIEW_TYPE_CONTENT -> R.layout.view_feed_content + else -> error("Unknown viewType: $viewType") } val view = LayoutInflater.from(parent.context).inflate(layoutResId, parent, false) view.layoutParams = RecyclerView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ).apply { bottomMargin = parent.resources.getDimensionPixelSize(R.dimen.spacing_8) } - return if (viewType == VIEW_TYPE_RANKING) { - RankingViewHolder(view, onClickItem) - } else { - ContentViewHolder(view, onClickItem) + return when (viewType) { + VIEW_TYPE_RANKING -> RankingViewHolder(view as FeedRankView, parent, onClickItem) + VIEW_TYPE_COMMUNITY -> CommunityViewHolder(view as FeedCommunityView, parent, onClickItem) + VIEW_TYPE_CONTENT -> ContentViewHolder(view as FeedContentView, parent, onClickItem) + else -> error("Unknown viewType: $viewType") } } @@ -55,50 +69,100 @@ class HomeFollowingNewsAdapter( } class RankingViewHolder( - itemView: View, + private val view: FeedRankView, + private val parent: ViewGroup, private val onClickItem: (HomeFollowingNewsUiItem) -> Unit - ) : NewsViewHolder(itemView) { - private val rankText = itemView.findViewById(R.id.tv_home_following_news_rank) - private val titleText = itemView.findViewById(R.id.tv_home_following_news_rank_title) - private val countText = itemView.findViewById(R.id.tv_home_following_news_rank_count) + ) : NewsViewHolder(view) { override fun bind(item: HomeFollowingNewsUiItem) { val ranking = item as HomeFollowingNewsUiItem.Ranking - rankText.text = ranking.rank.toString() - titleText.text = ranking.title - countText.text = ranking.body - itemView.setOnClickListener { onClickItem(ranking) } + val feedItem = FeedItem.Rank( + feedId = ranking.newsId, + imageUrl = ranking.thumbnailImageUrl.orEmpty(), + rankText = ranking.rank.toString(), + message = ranking.body.ifBlank { ranking.title }, + highlightRanges = emptyList() + ) + view.setFeedSize(feedSize(FeedVariant.Rank, parent)) + view.bind(feedItem) + bindImage(view.imageView(), feedItem.imageUrl) + view.setOnFeedClick { onClickItem(ranking) } + } + } + + class CommunityViewHolder( + private val view: FeedCommunityView, + private val parent: ViewGroup, + private val onClickItem: (HomeFollowingNewsUiItem) -> Unit + ) : NewsViewHolder(view) { + + override fun bind(item: HomeFollowingNewsUiItem) { + val community = item as HomeFollowingNewsUiItem.Content + val feedItem = FeedItem.Community( + feedId = community.newsId, + creatorId = community.targetId.toString(), + creatorName = community.creatorNickname, + creatorImageUrl = community.creatorProfileImageUrl, + postId = community.targetId.toString(), + bodyText = community.body.ifBlank { community.title }, + keywordText = "", + createdAtText = community.visibleFromText, + commentCount = 0, + likeCount = 0, + imageUrl = community.thumbnailImageUrl + ) + view.setFeedSize(feedSize(FeedVariant.Community, parent)) + view.bind(feedItem) + view.profileImageView().loadHomeCreatorProfileImage(feedItem.creatorImageUrl) + bindImage(view.communityImageView(), feedItem.imageUrl.orEmpty()) + view.setOnFeedClick { onClickItem(community) } } } class ContentViewHolder( - itemView: View, + private val view: FeedContentView, + private val parent: ViewGroup, private val onClickItem: (HomeFollowingNewsUiItem) -> Unit - ) : NewsViewHolder(itemView) { - private val profileImage = itemView.findViewById(R.id.iv_home_following_news_creator_profile) - private val nicknameText = itemView.findViewById(R.id.tv_home_following_news_creator_nickname) - private val createdAtText = itemView.findViewById(R.id.tv_home_following_news_created_at) - private val labelText = itemView.findViewById(R.id.tv_home_following_news_label) - private val titleText = itemView.findViewById(R.id.tv_home_following_news_title) - private val contentText = itemView.findViewById(R.id.tv_home_following_news_content) - private val thumbnailImage = itemView.findViewById(R.id.iv_home_following_news_thumbnail) + ) : NewsViewHolder(view) { override fun bind(item: HomeFollowingNewsUiItem) { val content = item as HomeFollowingNewsUiItem.Content - profileImage.loadHomeCreatorProfileImage(content.creatorProfileImageUrl) - nicknameText.text = content.creatorNickname - createdAtText.text = content.visibleFromText - labelText.setText(content.labelResId) - titleText.text = content.title - contentText.text = content.body - thumbnailImage.isVisible = !content.thumbnailImageUrl.isNullOrBlank() - content.thumbnailImageUrl?.let(thumbnailImage::loadUrl) - itemView.setOnClickListener { onClickItem(content) } + val feedItem = FeedItem.Content( + feedId = content.newsId, + creatorId = content.targetId.toString(), + creatorName = content.creatorNickname, + creatorImageUrl = content.creatorProfileImageUrl, + contentId = content.targetId.toString(), + contentTitle = content.title, + contentImageUrl = content.thumbnailImageUrl.orEmpty(), + createdAtText = content.visibleFromText + ) + view.setFeedSize(feedSize(FeedVariant.Content, parent)) + view.bind(feedItem) + bindImage(view.profileImageView(), feedItem.creatorImageUrl) + bindImage(view.contentImageView(), feedItem.contentImageUrl) + view.setOnFeedClick { onClickItem(content) } } } companion object { private const val VIEW_TYPE_RANKING = 0 private const val VIEW_TYPE_CONTENT = 1 + private const val VIEW_TYPE_COMMUNITY = 2 + + private fun feedSize(variant: FeedVariant, parent: ViewGroup): FeedSize { + val parentWidthPx = parent.width.takeIf { it > 0 } ?: parent.resources.displayMetrics.widthPixels + val availableWidthPx = parentWidthPx - parent.paddingLeft - parent.paddingRight + val availableWidthDp = (availableWidthPx / parent.resources.displayMetrics.density).roundToInt() + return FeedSize.from(variant, FeedWidthMode.ParentAvailable, availableWidthDp) + } + + private fun bindImage(imageView: android.widget.ImageView, url: String) { + if (url.isBlank()) { + imageView.setImageDrawable(null) + } else { + imageView.loadUrl(url) + } + } } } diff --git a/app/src/main/res/layout/fragment_v2_main_home.xml b/app/src/main/res/layout/fragment_v2_main_home.xml index 071111f5..d5a2d54a 100644 --- a/app/src/main/res/layout/fragment_v2_main_home.xml +++ b/app/src/main/res/layout/fragment_v2_main_home.xml @@ -264,15 +264,10 @@ android:layout_marginTop="@dimen/spacing_12" android:orientation="vertical"> - - diff --git a/app/src/main/res/layout/item_home_following_chat.xml b/app/src/main/res/layout/item_home_following_chat.xml index 1fbd39bf..26587081 100644 --- a/app/src/main/res/layout/item_home_following_chat.xml +++ b/app/src/main/res/layout/item_home_following_chat.xml @@ -1,7 +1,7 @@ - + android:layout_height="17dp" + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + + - + android:maxLines="1" + android:textColor="@color/white" + tools:text="마지막 대화 내용이 들어가는 부분입니다. 한 줄 넘어가는경우 말줄임" /> - + + diff --git a/app/src/main/res/layout/item_home_following_creator.xml b/app/src/main/res/layout/item_home_following_creator.xml index 33e35982..92758e05 100644 --- a/app/src/main/res/layout/item_home_following_creator.xml +++ b/app/src/main/res/layout/item_home_following_creator.xml @@ -1,15 +1,15 @@