diff --git a/app/build.gradle b/app/build.gradle index 22346c8c..f958aa90 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,7 +36,7 @@ android { minSdk 23 targetSdk 34 versionCode 174 - versionName "1.38.0" + versionName "1.39.0" } buildTypes { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt index e7001407..1701a341 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt @@ -72,6 +72,7 @@ class HomeFragment : BaseFragment(FragmentHomeBinding::infl private lateinit var auditionAdapter: AuditionBannerAdapter private lateinit var seriesDayOfWeekAdapter: HomeSeriesAdapter private lateinit var weelyChartAdapter: HomeWeeklyChartAdapter + private lateinit var recommendChannelAdapter: HomeRecommendChannelAdapter private lateinit var homeFreeContentAdapter: HomeContentAdapter private lateinit var curationAdapter: HomeCurationAdapter @@ -167,6 +168,7 @@ class HomeFragment : BaseFragment(FragmentHomeBinding::infl setupAudition() setupSeriesDayOfWeek() setupWeelyChart() + setupRecommendChannel() setupFreeContent() setupCuration() } @@ -860,6 +862,82 @@ class HomeFragment : BaseFragment(FragmentHomeBinding::infl } } + private fun setupRecommendChannel() { + val spSectionTitle = SpannableString(binding.tvRecommendChannel.text) + spSectionTitle.setSpan( + ForegroundColorSpan( + ContextCompat.getColor( + requireContext(), + R.color.color_3bb9f1 + ) + ), + 0, + 2, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + binding.tvRecommendChannel.text = spSectionTitle + + recommendChannelAdapter = HomeRecommendChannelAdapter( + onClickCreatorProfile = { + startActivity( + Intent(requireContext(), UserProfileActivity::class.java).apply { + putExtra(Constants.EXTRA_USER_ID, it) + } + ) + }, + onClickContentItem = { + startActivity( + Intent(requireContext(), AudioContentDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it) + } + ) + } + ) + + val recyclerView = binding.rvRecommendChannel + recyclerView.layoutManager = LinearLayoutManager( + context, + LinearLayoutManager.HORIZONTAL, + false + ) + recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + when (parent.getChildAdapterPosition(view)) { + 0 -> { + outRect.left = 0 + outRect.right = 8f.dpToPx().toInt() + } + + recommendChannelAdapter.itemCount - 1 -> { + outRect.left = 8f.dpToPx().toInt() + outRect.right = 0 + } + + else -> { + outRect.left = 8f.dpToPx().toInt() + outRect.right = 8f.dpToPx().toInt() + } + } + } + }) + recyclerView.adapter = recommendChannelAdapter + + viewModel.recommendChannelListLiveData.observe(viewLifecycleOwner) { + if (it.isNotEmpty()) { + binding.llRecommendChannel.visibility = View.VISIBLE + recommendChannelAdapter.addItems(it) + } else { + binding.llRecommendChannel.visibility = View.GONE + } + } + } + private fun setupFreeContent() { val spSectionTitle = SpannableString(binding.tvFreeContent.text) spSectionTitle.setSpan( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeRecommendChannelAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeRecommendChannelAdapter.kt new file mode 100644 index 00000000..b3779e34 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeRecommendChannelAdapter.kt @@ -0,0 +1,105 @@ +package kr.co.vividnext.sodalive.home + +import android.annotation.SuppressLint +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import coil.load +import coil.transform.CircleCropTransformation +import coil.transform.RoundedCornersTransformation +import kr.co.vividnext.sodalive.databinding.ItemHomeRecommendChannelBinding +import kr.co.vividnext.sodalive.extensions.moneyFormat + +class HomeRecommendChannelAdapter( + private val onClickCreatorProfile: (Long) -> Unit, + private val onClickContentItem: (Long) -> Unit +) : RecyclerView.Adapter() { + + private var items = mutableListOf() + + inner class ViewHolder( + private val binding: ItemHomeRecommendChannelBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: RecommendChannelResponse) { + binding.ivCreatorProfile.load(item.creatorProfileImageUrl) { + crossfade(true) + placeholder(android.R.drawable.ic_menu_gallery) + transformations(CircleCropTransformation()) + } + + binding.tvNickname.text = item.creatorNickname + binding.tvContentCount.text = item.contentCount.moneyFormat() + + binding.ivCreatorProfile.setOnClickListener { onClickCreatorProfile(item.channelId) } + binding.llCreatorProfile.setOnClickListener { onClickCreatorProfile(item.channelId) } + + item.contentList.forEachIndexed { index, content -> + if (index >= 3) return@forEachIndexed + + when (index) { + 0 -> { + binding.ivCover1.load(content.thumbnailImageUrl) { + crossfade(true) + placeholder(android.R.drawable.ic_menu_gallery) + transformations(RoundedCornersTransformation(12f)) + } + + binding.tvTitle1.text = content.title + binding.tvLikeCount1.text = content.likeCount.moneyFormat() + binding.tvCommentCount1.text = content.commentCount.moneyFormat() + + binding.llContent1.setOnClickListener { onClickContentItem(content.contentId) } + } + + 1 -> { + binding.ivCover2.load(content.thumbnailImageUrl) { + crossfade(true) + placeholder(android.R.drawable.ic_menu_gallery) + transformations(RoundedCornersTransformation(12f)) + } + + binding.tvTitle2.text = content.title + binding.tvLikeCount2.text = content.likeCount.moneyFormat() + binding.tvCommentCount2.text = content.commentCount.moneyFormat() + + binding.llContent2.setOnClickListener { onClickContentItem(content.contentId) } + } + + 2 -> { + binding.ivCover3.load(content.thumbnailImageUrl) { + crossfade(true) + placeholder(android.R.drawable.ic_menu_gallery) + transformations(RoundedCornersTransformation(12f)) + } + + binding.tvTitle3.text = content.title + binding.tvLikeCount3.text = content.likeCount.moneyFormat() + binding.tvCommentCount3.text = content.commentCount.moneyFormat() + + binding.llContent3.setOnClickListener { onClickContentItem(content.contentId) } + } + } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( + ItemHomeRecommendChannelBinding.inflate( + android.view.LayoutInflater.from(parent.context), + parent, + false + ) + ) + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position]) + } + + override fun getItemCount() = items.size + + @SuppressLint("NotifyDataSetChanged") + fun addItems(items: List) { + this.items.clear() + this.items.addAll(items) + notifyDataSetChanged() + } +} diff --git a/app/src/main/res/drawable-mdpi/ic_comment_white.png b/app/src/main/res/drawable-mdpi/ic_comment_white.png new file mode 100644 index 00000000..a62f55ca Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_comment_white.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_heart_white.png b/app/src/main/res/drawable-mdpi/ic_heart_white.png new file mode 100644 index 00000000..86b4c250 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_heart_white.png differ diff --git a/app/src/main/res/drawable/bg_home_recommend_channel.xml b/app/src/main/res/drawable/bg_home_recommend_channel.xml new file mode 100644 index 00000000..c5b4725e --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_channel.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/app/src/main/res/layout/item_home_recommend_channel.xml b/app/src/main/res/layout/item_home_recommend_channel.xml new file mode 100644 index 00000000..20c76b9b --- /dev/null +++ b/app/src/main/res/layout/item_home_recommend_channel.xml @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +