Merge pull request #5607 from abGit9/fix_stuttering_list_2

fix: resolve stuttering when scrolling to the bottom of channel/playlist videos list
This commit is contained in:
Bnyro 2024-02-25 12:56:20 +01:00 committed by GitHub
commit 066e01be51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 298 additions and 267 deletions

View File

@ -59,6 +59,8 @@ class ChannelFragment : DynamicLayoutManagerFragment() {
private var nextPages = Array<String?>(5) { null } private var nextPages = Array<String?>(5) { null }
private var searchChannelAdapter: SearchChannelAdapter? = null private var searchChannelAdapter: SearchChannelAdapter? = null
private var isAppBarFullyExpanded: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
channelName = args.channelName channelName = args.channelName
@ -86,14 +88,24 @@ class ChannelFragment : DynamicLayoutManagerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// Check if the AppBarLayout is fully expanded
binding.channelAppBar.addOnOffsetChangedListener { _, verticalOffset ->
isAppBarFullyExpanded = verticalOffset == 0
}
// Determine if the child can scroll up
binding.channelRefresh.setOnChildScrollUpCallback { _, _ ->
!isAppBarFullyExpanded
}
binding.channelRefresh.setOnRefreshListener { binding.channelRefresh.setOnRefreshListener {
fetchChannel() fetchChannel()
} }
binding.channelScrollView.viewTreeObserver.addOnScrollChangedListener { binding.channelRecView.viewTreeObserver.addOnScrollChangedListener {
val binding = _binding ?: return@addOnScrollChangedListener val binding = _binding ?: return@addOnScrollChangedListener
if (binding.channelScrollView.canScrollVertically(1) || isLoading) return@addOnScrollChangedListener if (binding.channelRecView.canScrollVertically(1) || isLoading) return@addOnScrollChangedListener
loadNextPage() loadNextPage()
} }
@ -199,7 +211,8 @@ class ChannelFragment : DynamicLayoutManagerFragment() {
isLoading = false isLoading = false
binding.channelRefresh.isRefreshing = false binding.channelRefresh.isRefreshing = false
binding.channelScrollView.isVisible = true binding.channelCoordinator.isVisible = true
binding.channelName.text = response.name binding.channelName.text = response.name
if (response.verified) { if (response.verified) {
binding.channelName binding.channelName

View File

@ -123,7 +123,6 @@ class PlaylistFragment : DynamicLayoutManagerFragment() {
} }
private fun fetchPlaylist() { private fun fetchPlaylist() {
binding.playlistScrollview.isGone = true
lifecycleScope.launch { lifecycleScope.launch {
val response = try { val response = try {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@ -136,12 +135,13 @@ class PlaylistFragment : DynamicLayoutManagerFragment() {
val binding = _binding ?: return@launch val binding = _binding ?: return@launch
playlistFeed = response.relatedStreams.toMutableList() playlistFeed = response.relatedStreams.toMutableList()
binding.playlistScrollview.isVisible = true
nextPage = response.nextpage nextPage = response.nextpage
playlistName = response.name playlistName = response.name
isLoading = false isLoading = false
ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail) ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail)
binding.playlistProgress.isGone = true binding.playlistProgress.isGone = true
binding.playlistAppBar.isVisible = true
binding.playlistRecView.isVisible = true
binding.playlistName.text = response.name binding.playlistName.text = response.name
binding.playlistInfo.text = getChannelAndVideoString(response, response.videos) binding.playlistInfo.text = getChannelAndVideoString(response, response.videos)
@ -312,8 +312,8 @@ class PlaylistFragment : DynamicLayoutManagerFragment() {
} }
}) })
binding.playlistScrollview.viewTreeObserver.addOnScrollChangedListener { binding.playlistRecView.viewTreeObserver.addOnScrollChangedListener {
if (_binding?.playlistScrollview?.canScrollVertically(1) == false && if (_binding?.playlistRecView?.canScrollVertically(1) == false &&
!isLoading !isLoading
) { ) {
// append more playlists to the recycler view // append more playlists to the recycler view

View File

@ -6,18 +6,29 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ScrollView <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/channel_scrollView" android:id="@+id/channel_coordinator"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:visibility="gone">
android:visibility="invisible"
tools:context=".ui.fragments.ChannelFragment"> <com.google.android.material.appbar.AppBarLayout
android:id="@+id/channel_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/channel_collapsing_tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll"
app:titleCollapseMode="scale">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical"
app:layout_collapseMode="pin">
<ImageView <ImageView
android:id="@+id/channel_banner" android:id="@+id/channel_banner"
@ -72,15 +83,15 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/channel_share" android:id="@+id/channel_share"
android:tooltipText="@string/share"
style="@style/ElevatedIconButton" style="@style/ElevatedIconButton"
android:tooltipText="@string/share"
app:icon="@drawable/ic_share" app:icon="@drawable/ic_share"
tools:targetApi="m" /> tools:targetApi="m" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/notification_bell" android:id="@+id/notification_bell"
android:tooltipText="@string/notifications"
style="@style/ElevatedIconButton" style="@style/ElevatedIconButton"
android:tooltipText="@string/notifications"
app:icon="@drawable/ic_notification" app:icon="@drawable/ic_notification"
tools:targetApi="m" /> tools:targetApi="m" />
@ -153,18 +164,17 @@
</HorizontalScrollView> </HorizontalScrollView>
<RelativeLayout </LinearLayout>
android:layout_width="match_parent"
android:layout_height="wrap_content" </com.google.android.material.appbar.CollapsingToolbarLayout>
android:descendantFocusability="blocksDescendants">
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/channel_recView" android:id="@+id/channel_recView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:nestedScrollingEnabled="false" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
</ScrollView>
</com.github.libretube.ui.views.CustomSwipeToRefresh> </com.github.libretube.ui.views.CustomSwipeToRefresh>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -10,14 +10,29 @@
android:id="@+id/playlist_progress" android:id="@+id/playlist_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:visibility="gone"
android:layout_centerVertical="true" android:layout_gravity="center" />
android:visibility="gone" />
<ScrollView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/playlist_scrollview" android:id="@+id/playlist_recView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:clipToPadding="false"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/playlist_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/playlist_collapsing_tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll"
app:titleCollapseMode="scale">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -137,21 +152,14 @@
</LinearLayout> </LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/playlist_recView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:nestedScrollingEnabled="false" />
</RelativeLayout>
</LinearLayout> </LinearLayout>
</ScrollView>
</RelativeLayout> </com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>