fix: only show/hide scroll to top button at end of scrolling

This commit is contained in:
Bnyro 2025-01-16 17:37:30 +01:00
parent f519168422
commit 5e53df095a
2 changed files with 29 additions and 39 deletions

View File

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -15,6 +14,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.databinding.FragmentCommentsBinding import com.github.libretube.databinding.FragmentCommentsBinding
@ -31,8 +31,6 @@ class CommentsMainFragment : Fragment() {
private val binding get() = _binding!! private val binding get() = _binding!!
private val viewModel: CommentsViewModel by activityViewModels() private val viewModel: CommentsViewModel by activityViewModels()
private var scrollListener: ViewTreeObserver.OnScrollChangedListener? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -57,20 +55,19 @@ class CommentsMainFragment : Fragment() {
viewModel.setCommentsPosition(POSITION_START) viewModel.setCommentsPosition(POSITION_START)
} }
var restoredScrollPosition = viewModel.currentCommentsPosition.value == 0 binding.commentsRV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
binding.commentsRV.viewTreeObserver.addOnScrollChangedListener { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
// hide or show the scroll to top button if (newState != RecyclerView.SCROLL_STATE_IDLE) return
commentsSheet?.binding?.btnScrollToTop?.isVisible =
viewModel.currentCommentsPosition.value != 0
val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition() val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
if (!restoredScrollPosition) {
restoredScrollPosition = firstVisiblePosition >= (viewModel.currentCommentsPosition.value ?: 0)
return@addOnScrollChangedListener
}
// hide or show the scroll to top button
commentsSheet?.binding?.btnScrollToTop?.isVisible = firstVisiblePosition != 0
viewModel.setCommentsPosition(firstVisiblePosition) viewModel.setCommentsPosition(firstVisiblePosition)
super.onScrollStateChanged(recyclerView, newState)
} }
})
commentsSheet?.updateFragmentInfo(false, getString(R.string.comments)) commentsSheet?.updateFragmentInfo(false, getString(R.string.comments))
@ -89,14 +86,17 @@ class CommentsMainFragment : Fragment() {
} }
binding.commentsRV.adapter = commentPagingAdapter binding.commentsRV.adapter = commentPagingAdapter
var scrollPositionRestoreRequired = viewModel.currentCommentsPosition.value == 0
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) { repeatOnLifecycle(Lifecycle.State.STARTED) {
launch { launch {
commentPagingAdapter.loadStateFlow.collect { commentPagingAdapter.loadStateFlow.collect {
binding.progress.isVisible = it.refresh is LoadState.Loading binding.progress.isVisible = it.refresh is LoadState.Loading
if (!restoredScrollPosition && it.refresh is LoadState.NotLoading) { if (!scrollPositionRestoreRequired && it.refresh is LoadState.NotLoading) {
viewModel.currentCommentsPosition.value?.let { position -> viewModel.currentCommentsPosition.value?.let { position ->
scrollPositionRestoreRequired = false
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
binding.commentsRV.scrollToPosition(position) binding.commentsRV.scrollToPosition(position)
} }
@ -129,12 +129,6 @@ class CommentsMainFragment : Fragment() {
} }
} }
override fun onPause() {
super.onPause()
binding.commentsRV.viewTreeObserver.removeOnScrollChangedListener(scrollListener)
scrollListener = null
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View File

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -19,6 +18,7 @@ import androidx.paging.LoadState
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.api.obj.Comment import com.github.libretube.api.obj.Comment
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
@ -37,8 +37,6 @@ class CommentsRepliesFragment : Fragment() {
private val viewModel: CommentsViewModel by activityViewModels() private val viewModel: CommentsViewModel by activityViewModels()
private var scrollListener: ViewTreeObserver.OnScrollChangedListener? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -97,15 +95,19 @@ class CommentsRepliesFragment : Fragment() {
viewModel.setRepliesPosition(POSITION_START) viewModel.setRepliesPosition(POSITION_START)
} }
scrollListener = ViewTreeObserver.OnScrollChangedListener { binding.commentsRV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
// save the last scroll position to become used next time when the sheet is opened override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
viewModel.setRepliesPosition(layoutManager.findFirstVisibleItemPosition()) if (newState != RecyclerView.SCROLL_STATE_IDLE) return
// hide or show the scroll to top button
commentsSheet?.binding?.btnScrollToTop?.isVisible =
viewModel.currentRepliesPosition.value != 0
}
binding.commentsRV.viewTreeObserver.addOnScrollChangedListener(scrollListener) val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
// hide or show the scroll to top button
commentsSheet?.binding?.btnScrollToTop?.isVisible = firstVisiblePosition != 0
viewModel.setRepliesPosition(firstVisiblePosition)
super.onScrollStateChanged(recyclerView, newState)
}
})
val commentRepliesFlow = Pager(PagingConfig(20, enablePlaceholders = false)) { val commentRepliesFlow = Pager(PagingConfig(20, enablePlaceholders = false)) {
CommentRepliesPagingSource(videoId, comment) CommentRepliesPagingSource(videoId, comment)
@ -128,12 +130,6 @@ class CommentsRepliesFragment : Fragment() {
} }
} }
override fun onPause() {
super.onPause()
binding.commentsRV.viewTreeObserver.removeOnScrollChangedListener(scrollListener)
scrollListener = null
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null