From d3060d7a89687a883b9ea3a39e4b8971b037fd45 Mon Sep 17 00:00:00 2001 From: BuNa <56534241+tmdgh1592@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:15:31 +0900 Subject: [PATCH] =?UTF-8?q?Feature/#777=20=ED=96=89=EC=82=AC=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20=EB=A7=A8=20?= =?UTF-8?q?=EC=9C=84=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20(#834)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 컨퍼런스 화면에서 맨 위로 스크롤하는 기능 구현 * feat: 스크랩 화면에서 맨 위로 스크롤하는 기능 구현 * feat: 대회 화면에서 맨 위로 스크롤하는 기능 구현 * refactor: ScrollTopListener의 클릭리스너를 내부에서 설정하도록 변경 * refactor(ScrollTopListener): getScrollUpStandardPosition() 메서드를 expression 형식으로 변경 * refactor(ScrollTopListener): 메서드 배치 순서 변경 --- .../presentation/common/ScrollTopListener.kt | 53 +++++++++++++++++++ .../ui/competitionList/CompetitionFragment.kt | 4 ++ .../ui/conferenceList/ConferenceFragment.kt | 4 ++ .../ScrappedEventFragment.kt | 4 ++ .../src/main/res/drawable/ic_all_arrow_up.xml | 9 ++++ .../main/res/layout/fragment_competition.xml | 20 +++++-- .../main/res/layout/fragment_conference.xml | 16 ++++++ .../res/layout/fragment_scrapped_event.xml | 16 ++++++ 8 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 android/2023-emmsale/app/src/main/java/com/emmsale/presentation/common/ScrollTopListener.kt create mode 100644 android/2023-emmsale/app/src/main/res/drawable/ic_all_arrow_up.xml diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/common/ScrollTopListener.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/common/ScrollTopListener.kt new file mode 100644 index 000000000..e41517dc3 --- /dev/null +++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/common/ScrollTopListener.kt @@ -0,0 +1,53 @@ +package com.emmsale.presentation.common + +import android.view.View +import androidx.core.view.isVisible +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.emmsale.R + +class ScrollTopListener( + private val targetView: View, +) : RecyclerView.OnScrollListener() { + private val isLandScape = getIsLandscape() + private val scrollUpStandardPosition = getScrollUpStandardPosition(isLandScape) + + private fun getIsLandscape(): Boolean { + return targetView.context.resources.getBoolean(R.bool.is_landscape) + } + + private fun getScrollUpStandardPosition(isLandScape: Boolean): Int = if (isLandScape) { + LANDSCAPE_SCROLL_UP_STANDARD_POSITION + } else { + PORTRAIT_SCROLL_UP_STANDARD_POSITION + } + + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + val layoutManager = recyclerView.layoutManager as GridLayoutManager + val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() + + setupTargetView(recyclerView, lastVisibleItemPosition) + } + + private fun setupTargetView(recyclerView: RecyclerView, lastVisibleItemPosition: Int) { + setupTargetViewClickListener(recyclerView) + targetView.isVisible = isVisibleTargetView(lastVisibleItemPosition) + } + + private fun setupTargetViewClickListener(recyclerView: RecyclerView) { + if (targetView.hasOnClickListeners()) return + + targetView.setOnClickListener { + recyclerView.smoothScrollToPosition(0) + } + } + + private fun isVisibleTargetView(lastVisibleItemPosition: Int) = + lastVisibleItemPosition >= scrollUpStandardPosition + + companion object { + private const val PORTRAIT_SCROLL_UP_STANDARD_POSITION = 3 + private const val LANDSCAPE_SCROLL_UP_STANDARD_POSITION = 6 + } +} diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/competitionList/CompetitionFragment.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/competitionList/CompetitionFragment.kt index ddb8a76c0..40db18977 100644 --- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/competitionList/CompetitionFragment.kt +++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/competitionList/CompetitionFragment.kt @@ -9,6 +9,7 @@ import com.emmsale.R import com.emmsale.data.model.Event import com.emmsale.databinding.FragmentCompetitionBinding import com.emmsale.presentation.base.BaseFragment +import com.emmsale.presentation.common.ScrollTopListener import com.emmsale.presentation.common.extension.getSerializableExtraCompat import com.emmsale.presentation.common.views.FilterTag import com.emmsale.presentation.common.views.filterChipOf @@ -69,6 +70,9 @@ class CompetitionFragment : BaseFragment() { private fun initEventRecyclerView() { binding.rvEvents.adapter = eventAdapter + binding.rvEvents.addOnScrollListener( + ScrollTopListener(targetView = binding.fabScrollTop), + ) } private fun setupEventsObserver() { diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/conferenceList/ConferenceFragment.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/conferenceList/ConferenceFragment.kt index d9a5907f3..c848034ff 100644 --- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/conferenceList/ConferenceFragment.kt +++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/conferenceList/ConferenceFragment.kt @@ -9,6 +9,7 @@ import com.emmsale.R import com.emmsale.data.model.Event import com.emmsale.databinding.FragmentConferenceBinding import com.emmsale.presentation.base.BaseFragment +import com.emmsale.presentation.common.ScrollTopListener import com.emmsale.presentation.common.extension.getSerializableExtraCompat import com.emmsale.presentation.common.views.FilterTag import com.emmsale.presentation.common.views.filterChipOf @@ -67,6 +68,9 @@ class ConferenceFragment : BaseFragment() { private fun initEventRecyclerView() { binding.rvEvents.adapter = eventAdapter + binding.rvEvents.addOnScrollListener( + ScrollTopListener(targetView = binding.fabScrollTop), + ) } private fun setupEventsObserver() { diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/scrappedEventList/ScrappedEventFragment.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/scrappedEventList/ScrappedEventFragment.kt index 6ec3993cb..5c6ca22af 100644 --- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/scrappedEventList/ScrappedEventFragment.kt +++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/scrappedEventList/ScrappedEventFragment.kt @@ -6,6 +6,7 @@ import androidx.fragment.app.viewModels import com.emmsale.R import com.emmsale.databinding.FragmentScrappedEventBinding import com.emmsale.presentation.base.BaseFragment +import com.emmsale.presentation.common.ScrollTopListener import com.emmsale.presentation.ui.eventDetail.EventDetailActivity import com.emmsale.presentation.ui.scrappedEventList.recyclerView.ScrappedEventAdapter import com.emmsale.presentation.ui.scrappedEventList.uiState.ScrappedEventUiState @@ -34,6 +35,9 @@ class ScrappedEventFragment : BaseFragment() { private fun initBinding() { binding.vm = viewModel binding.rvScrappedEvents.adapter = scrappedEventsAdapter + binding.rvScrappedEvents.addOnScrollListener( + ScrollTopListener(targetView = binding.fabScrollTop), + ) } private fun setUpScrappedEvents() { diff --git a/android/2023-emmsale/app/src/main/res/drawable/ic_all_arrow_up.xml b/android/2023-emmsale/app/src/main/res/drawable/ic_all_arrow_up.xml new file mode 100644 index 000000000..d7d1b73ef --- /dev/null +++ b/android/2023-emmsale/app/src/main/res/drawable/ic_all_arrow_up.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/2023-emmsale/app/src/main/res/layout/fragment_competition.xml b/android/2023-emmsale/app/src/main/res/layout/fragment_competition.xml index 9cba03a03..f9713668a 100644 --- a/android/2023-emmsale/app/src/main/res/layout/fragment_competition.xml +++ b/android/2023-emmsale/app/src/main/res/layout/fragment_competition.xml @@ -21,8 +21,7 @@ + android:layout_height="match_parent"> - + + + + + +