Skip to content

Commit

Permalink
[AN/USER] feat: 축제 목록 화면 인기 축제 목록에 무한 스크롤을 적용한다(#735) (#736)
Browse files Browse the repository at this point in the history
* feat(PopularFestivalForegroundAdapter): foreground 인기 축제 목록을 무한 스크롤 가능하게 변경한다.

* refactor(PopularFestivalViewPagerAdapter): 변수 이름 카멜 케이스로 변경

* refactor(FestivalListPopularViewHolder): DotIndicator 는 터치해서 이동할 수 없다

* refactor(PopularFestivalViewPagerAdapter): initialPosition 계산 변수로 분리

* fix(PopularFestivalViewPagerAdapter): 축제 목록이 변경되면 포지션 초기화

* feat(PopularFestivalViewPagerAdapter): 미리 로딩하는 좌우 화면 개수를 2로 변경한다

* feat(PopularFestivalViewPagerAdapter): 인기 축제 개수가 0 개면 인기 축제 목록이 보이지 않는다
  • Loading branch information
SeongHoonC authored Feb 28, 2024
1 parent 6e066bd commit c41210d
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,27 @@ class FestivalListFragment : Fragment() {
}

private fun handleSuccess(uiState: FestivalListUiState.Success) {
festivalListAdapter.submitList(
listOf(
uiState.popularFestivals,
FestivalTabUiState {
val festivalFilter = when (it) {
0 -> FestivalFilterUiState.PROGRESS
1 -> FestivalFilterUiState.PLANNED
else -> FestivalFilterUiState.PROGRESS
}
vm.loadFestivals(festivalFilter)
},
) + uiState.festivals,
val items = uiState.getItems()
festivalListAdapter.submitList(items)
}

private fun FestivalListUiState.Success.getItems(): List<Any> {
val items = mutableListOf<Any>()
if (popularFestivalUiState.festivals.isNotEmpty()) {
items.add(popularFestivalUiState)
}
items.add(
FestivalTabUiState {
val festivalFilter = when (it) {
0 -> FestivalFilterUiState.PROGRESS
1 -> FestivalFilterUiState.PLANNED
else -> FestivalFilterUiState.PROGRESS
}
vm.loadFestivals(festivalFilter)
},
)
items.addAll(festivals)
return items.toList()
}

private fun showSchoolDetail() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class FestivalListViewModel @Inject constructor(
_uiState.value = FestivalListUiState.Success(
PopularFestivalUiState(
title = popularFestivals.title,
popularFestivals = popularFestivals.festivals.map { it.toUiState() },
festivals = popularFestivals.festivals.map { it.toUiState() },
),
festivals = festivalsPage.festivals.map { it.toUiState() },
isLastPage = festivalsPage.isLastPage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ class FestivalListPopularViewHolder(val binding: ItemFestivalListPopularBinding)
init {
TabLayoutMediator(
binding.tlDotIndicator,
binding.vpPopularFestivalForeground,
) { tab, position -> }.attach()
binding.vpPopularFestivalBackground,
) { tab, position ->
tab.view.isClickable = false
}.attach()
}

fun bind(popularFestivalUiState: PopularFestivalUiState) {
binding.tvPopularFestivalTitle.text = popularFestivalUiState.title
popularFestivalViewPager.submitList(popularFestivalUiState.popularFestivals)
popularFestivalViewPager.submitList(popularFestivalUiState.festivals)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.festago.festago.presentation.ui.home.festivallist.uistate.FestivalIte
import kotlin.math.abs

class PopularFestivalViewPagerAdapter(
foregroundViewPager: ViewPager2,
private val foregroundViewPager: ViewPager2,
backgroundViewPager: ViewPager2,
private val onPopularFestivalSelected: (FestivalItemUiState) -> Unit,
) {
Expand All @@ -24,22 +24,23 @@ class PopularFestivalViewPagerAdapter(
foregroundViewPager.adapter = foregroundAdapter
backgroundViewPager.adapter = backgroundAdapter

setTargetItemOnPageSelected(viewpager = foregroundViewPager, target = backgroundViewPager)
setTargetItemOnPageSelected(viewPager = foregroundViewPager, target = backgroundViewPager)
narrowSpaceViewPager(viewPager = foregroundViewPager)
setOffscreenPagesLimit(foregroundViewPager, PAGE_LIMIT)
setOffscreenPagesLimit(backgroundViewPager, PAGE_LIMIT)
backgroundViewPager.isUserInputEnabled = false
}

private fun setTargetItemOnPageSelected(viewpager: ViewPager2, target: ViewPager2) {
private fun setTargetItemOnPageSelected(viewPager: ViewPager2, target: ViewPager2) {
val onPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
target.setCurrentItem(position, false)
onPopularFestivalSelected(popularFestivals[position])
val itemIndex = position % popularFestivals.size
target.setCurrentItem(itemIndex, false)
onPopularFestivalSelected(popularFestivals[itemIndex])
}
}
viewpager.registerOnPageChangeCallback(onPageChangeCallback)
viewPager.registerOnPageChangeCallback(onPageChangeCallback)
}

private fun narrowSpaceViewPager(viewPager: ViewPager2) {
Expand Down Expand Up @@ -85,10 +86,20 @@ class PopularFestivalViewPagerAdapter(
}

fun submitList(festivals: List<FestivalItemUiState>) {
val lastFestivals = popularFestivals.toList()
popularFestivals.clear()
popularFestivals.addAll(festivals)
foregroundAdapter.submitList(festivals)
backgroundAdapter.submitList(festivals)

if (lastFestivals != festivals) {
initItemPosition()
}
}

private fun initItemPosition() {
val initialPosition = Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2 % popularFestivals.size)
foregroundViewPager.setCurrentItem(initialPosition, false)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
package com.festago.festago.presentation.ui.home.festivallist.popularfestival.foreground

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.festago.festago.presentation.ui.home.festivallist.uistate.FestivalItemUiState

class PopularFestivalForegroundAdapter :
ListAdapter<FestivalItemUiState, PopularFestivalForegroundViewHolder>(diffUtil) {
class PopularFestivalForegroundAdapter(festivals: List<FestivalItemUiState> = listOf()) :
RecyclerView.Adapter<PopularFestivalForegroundViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PopularFestivalForegroundViewHolder {
private val _festivals = festivals.toMutableList()

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): PopularFestivalForegroundViewHolder {
return PopularFestivalForegroundViewHolder.of(parent)
}

override fun onBindViewHolder(holder: PopularFestivalForegroundViewHolder, position: Int) {
holder.bind(getItem(position))
holder.bind(_festivals[position % _festivals.size])
}

companion object {
val diffUtil = object : DiffUtil.ItemCallback<FestivalItemUiState>() {
override fun areItemsTheSame(
oldItem: FestivalItemUiState,
newItem: FestivalItemUiState,
): Boolean {
return oldItem.id == newItem.id
}
override fun getItemCount(): Int = Int.MAX_VALUE

override fun areContentsTheSame(
oldItem: FestivalItemUiState,
newItem: FestivalItemUiState,
): Boolean {
return oldItem == newItem
}
fun submitList(festivals: List<FestivalItemUiState>) {
if (_festivals.toList() == festivals) {
return
}
_festivals.clear()
_festivals.addAll(festivals)
notifyDataSetChanged()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sealed interface FestivalListUiState {
object Loading : FestivalListUiState

data class Success(
val popularFestivals: PopularFestivalUiState,
val popularFestivalUiState: PopularFestivalUiState,
val festivals: List<FestivalItemUiState>,
val isLastPage: Boolean,
) : FestivalListUiState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package com.festago.festago.presentation.ui.home.festivallist.uistate

data class PopularFestivalUiState(
val title: String,
val popularFestivals: List<FestivalItemUiState>,
val festivals: List<FestivalItemUiState>,
)

0 comments on commit c41210d

Please sign in to comment.