[Android] Add the fast scroller to the video list

Nicolas Pomepuy git at videolan.org
Tue Jun 1 12:17:27 UTC 2021


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Jun  1 06:07:01 2021 +0200| [c53946889b31eb3b92f2737d5180d9edfb7ac770] | committer: Nicolas Pomepuy

Add the fast scroller to the video list

Fixes #2039

> https://code.videolan.org/videolan/vlc-android/commit/c53946889b31eb3b92f2737d5180d9edfb7ac770
---

 application/vlc-android/res/layout/video_grid.xml       | 10 ++++++++--
 .../src/org/videolan/vlc/gui/video/VideoGridFragment.kt | 11 ++++++++++-
 .../src/org/videolan/vlc/gui/video/VideoListAdapter.kt  |  5 ++++-
 .../vlc/providers/medialibrary/VideoGroupsProvider.kt   | 17 ++++++++++-------
 4 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/application/vlc-android/res/layout/video_grid.xml b/application/vlc-android/res/layout/video_grid.xml
index 8c8fa7ef7..3c2832131 100644
--- a/application/vlc-android/res/layout/video_grid.xml
+++ b/application/vlc-android/res/layout/video_grid.xml
@@ -44,8 +44,7 @@
                     android:gravity="center"
                     android:numColumns="auto_fit"
                     android:padding="@dimen/half_default_margin"
-                    android:scrollbarStyle="outsideOverlay"
-                    android:scrollbars="vertical"
+                    android:scrollbars="none"
                     android:stretchMode="none" />
         </org.videolan.vlc.gui.view.SwipeRefreshLayout>
 
@@ -58,5 +57,12 @@
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toTopOf="parent" />
+
+        <org.videolan.vlc.gui.view.FastScroller
+                android:id="@+id/fast_scroller"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:visibility="invisible"
+                app:layout_constraintEnd_toEndOf="parent" />
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>
\ No newline at end of file
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
index fc961fc09..2ee48171a 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
@@ -27,12 +27,15 @@ import android.util.Log
 import android.view.*
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.view.ActionMode
+import androidx.coordinatorlayout.widget.CoordinatorLayout
 import androidx.fragment.app.FragmentActivity
 import androidx.lifecycle.Observer
 import androidx.lifecycle.lifecycleScope
 import androidx.paging.PagedList
 import androidx.recyclerview.widget.RecyclerView
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import com.google.android.material.appbar.AppBarLayout
+import com.google.android.material.floatingactionbutton.FloatingActionButton
 import kotlinx.coroutines.*
 import kotlinx.coroutines.flow.onEach
 import org.videolan.medialibrary.interfaces.Medialibrary
@@ -57,6 +60,7 @@ import org.videolan.vlc.gui.helpers.UiTools
 import org.videolan.vlc.gui.helpers.UiTools.addToGroup
 import org.videolan.vlc.gui.helpers.UiTools.addToPlaylist
 import org.videolan.vlc.gui.view.EmptyLoadingState
+import org.videolan.vlc.gui.view.FastScroller
 import org.videolan.vlc.media.MediaUtils
 import org.videolan.vlc.media.PlaylistManager
 import org.videolan.vlc.media.getAll
@@ -97,7 +101,10 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
         if (!::videoListAdapter.isInitialized) {
             val seenMarkVisible = settings.getBoolean("media_seen", true)
             videoListAdapter = VideoListAdapter(seenMarkVisible)
-            dataObserver = videoListAdapter.onAnyChange { updateEmptyView() }
+            dataObserver = videoListAdapter.onAnyChange {
+                updateEmptyView()
+                if (::binding.isInitialized) binding.fastScroller.setRecyclerView(binding.videoGrid, viewModel.provider)
+            }
             multiSelectHelper = videoListAdapter.multiSelectHelper
             val folder = if (savedInstanceState != null) savedInstanceState.getParcelable<Folder>(KEY_FOLDER)
             else arguments?.getParcelable(KEY_FOLDER)
@@ -215,6 +222,8 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
         super.onActivityCreated(savedInstanceState)
         swipeRefreshLayout.setOnRefreshListener(this)
         binding.videoGrid.adapter = videoListAdapter
+        binding.fastScroller.attachToCoordinator(binding.videoGrid.rootView.findViewById<View>(R.id.appbar) as AppBarLayout, binding.videoGrid.rootView.findViewById<View>(R.id.coordinator) as CoordinatorLayout, binding.videoGrid.rootView.findViewById<View>(R.id.fab) as FloatingActionButton)
+        binding.fastScroller.setRecyclerView(binding.videoGrid, viewModel.provider)
     }
 
     override fun onResume() {
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.kt
index 1b65ad23a..fe6286399 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.kt
@@ -51,6 +51,7 @@ import org.videolan.tools.safeOffer
 import org.videolan.vlc.BR
 import org.videolan.vlc.R
 import org.videolan.vlc.gui.helpers.*
+import org.videolan.vlc.gui.view.FastScroller
 import org.videolan.vlc.util.generateResolutionClass
 import org.videolan.vlc.util.scope
 import org.videolan.vlc.viewmodels.mobile.VideoGroupingType
@@ -58,7 +59,7 @@ import org.videolan.vlc.viewmodels.mobile.VideoGroupingType
 private const val TAG = "VLC/VideoListAdapter"
 
 class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
-) : PagedListAdapter<MediaLibraryItem, VideoListAdapter.ViewHolder>(VideoItemDiffCallback),
+) : PagedListAdapter<MediaLibraryItem, VideoListAdapter.ViewHolder>(VideoItemDiffCallback), FastScroller.SeparatedAdapter,
         MultiSelectAdapter<MediaLibraryItem>, IEventsSource<VideoAction> by EventsSource() {
 
     var isListMode = false
@@ -268,6 +269,8 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
     fun setSeenMediaMarkerVisible(seenMediaMarkerVisible: Boolean) {
         isSeenMediaMarkerVisible = seenMediaMarkerVisible
     }
+
+    override fun hasSections() = true
 }
 
 @BindingAdapter("time", "resolution")
diff --git a/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/VideoGroupsProvider.kt b/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/VideoGroupsProvider.kt
index 853baa5a5..fe1fecede 100644
--- a/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/VideoGroupsProvider.kt
+++ b/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/VideoGroupsProvider.kt
@@ -9,22 +9,25 @@ import org.videolan.medialibrary.media.MediaLibraryItem
 import org.videolan.tools.Settings
 import org.videolan.vlc.viewmodels.SortableModel
 
-
 class VideoGroupsProvider(context: Context, model: SortableModel) : MedialibraryProvider<MediaLibraryItem>(context, model) {
     override fun canSortByDuration() = true
     override fun canSortByInsertionDate() = true
     override fun canSortByLastModified() = true
     override fun canSortByMediaNumber() = true
 
-    override fun getAll() : Array<VideoGroup> = medialibrary.getVideoGroups(sort, desc, getTotalCount(), 0)
+    override fun getAll(): Array<VideoGroup> = medialibrary.getVideoGroups(sort, desc, getTotalCount(), 0)
 
     override fun getTotalCount() = medialibrary.getVideoGroupsCount(model.filterQuery)
 
-    override fun getPage(loadSize: Int, startposition: Int) : Array<MediaLibraryItem> = if (model.filterQuery.isNullOrEmpty()) {
-        medialibrary.getVideoGroups(sort, desc, loadSize, startposition)
-    } else {
-        medialibrary.searchVideoGroups(model.filterQuery, sort, desc, loadSize, startposition)
-    }.extractSingles().also { if (Settings.showTvUi) completeHeaders(it, startposition) }
+    override fun getPage(loadSize: Int, startposition: Int): Array<MediaLibraryItem> {
+        val medias = if (model.filterQuery.isNullOrEmpty()) {
+            medialibrary.getVideoGroups(sort, desc, loadSize, startposition)
+        } else {
+            medialibrary.searchVideoGroups(model.filterQuery, sort, desc, loadSize, startposition)
+        }.extractSingles().also { if (Settings.showTvUi) completeHeaders(it, startposition) }
+        model.viewModelScope.launch { completeHeaders(medias, startposition) }
+        return medias
+    }
 }
 
 private fun Array<VideoGroup>.extractSingles() = map {



More information about the Android mailing list