From f009a2edb8991636495081df8ec02c2407479a05 Mon Sep 17 00:00:00 2001 From: klaus Date: Thu, 25 Jun 2026 23:34:11 +0900 Subject: [PATCH] =?UTF-8?q?feat(home):=20=ED=8C=94=EB=A1=9C=EC=9E=89=20?= =?UTF-8?q?=EC=86=8C=EC=8B=9D=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/home/ui/HomeFollowingNewsAdapter.kt | 104 +++++++++++++++ .../item_home_following_news_content.xml | 118 ++++++++++++++++++ .../layout/item_home_following_news_rank.xml | 42 +++++++ 3 files changed, 264 insertions(+) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt create mode 100644 app/src/main/res/layout/item_home_following_news_content.xml create mode 100644 app/src/main/res/layout/item_home_following_news_rank.xml 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 new file mode 100644 index 00000000..7c7466e5 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt @@ -0,0 +1,104 @@ +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.model.HomeFollowingNewsUiItem + +class HomeFollowingNewsAdapter( + private val onClickItem: (HomeFollowingNewsUiItem) -> Unit = {} +) : RecyclerView.Adapter() { + private var items: List = emptyList() + + fun submitItems(items: List) { + this.items = items + notifyDataSetChanged() + } + + override fun getItemViewType(position: Int): Int = when (items[position]) { + is HomeFollowingNewsUiItem.Ranking -> VIEW_TYPE_RANKING + is HomeFollowingNewsUiItem.Content -> 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 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) + } + } + + override fun onBindViewHolder(holder: NewsViewHolder, position: Int) { + holder.bind(items[position]) + } + + override fun getItemCount(): Int = items.size + + sealed class NewsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + abstract fun bind(item: HomeFollowingNewsUiItem) + } + + class RankingViewHolder( + itemView: View, + 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) + + 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) } + } + } + + class ContentViewHolder( + itemView: View, + 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) + + 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) } + } + } + + companion object { + private const val VIEW_TYPE_RANKING = 0 + private const val VIEW_TYPE_CONTENT = 1 + } +} diff --git a/app/src/main/res/layout/item_home_following_news_content.xml b/app/src/main/res/layout/item_home_following_news_content.xml new file mode 100644 index 00000000..95449b9b --- /dev/null +++ b/app/src/main/res/layout/item_home_following_news_content.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_home_following_news_rank.xml b/app/src/main/res/layout/item_home_following_news_rank.xml new file mode 100644 index 00000000..297b0849 --- /dev/null +++ b/app/src/main/res/layout/item_home_following_news_rank.xml @@ -0,0 +1,42 @@ + + + + + + + + +