[Android] Fix TV item focus restoration + initial state

Nicolas Pomepuy git at videolan.org
Mon Nov 23 13:40:34 CET 2020


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Fri Nov 13 11:20:23 2020 +0100| [956a076497e34ac3b958c9b9c759c26dae0afedc] | committer: Nicolas Pomepuy

Fix TV item focus restoration + initial state

Fixes #1539
Fixes #1540

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

 .../television/ui/browser/BaseBrowserTvFragment.kt | 38 ++++++++++++++++++++--
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/application/television/src/main/java/org/videolan/television/ui/browser/BaseBrowserTvFragment.kt b/application/television/src/main/java/org/videolan/television/ui/browser/BaseBrowserTvFragment.kt
index 753b8e874..23ce189a3 100644
--- a/application/television/src/main/java/org/videolan/television/ui/browser/BaseBrowserTvFragment.kt
+++ b/application/television/src/main/java/org/videolan/television/ui/browser/BaseBrowserTvFragment.kt
@@ -42,7 +42,6 @@ import androidx.constraintlayout.widget.ConstraintSet
 import androidx.databinding.BindingAdapter
 import androidx.fragment.app.Fragment
 import androidx.leanback.app.BackgroundManager
-import androidx.lifecycle.Observer
 import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager
@@ -53,6 +52,7 @@ import kotlinx.coroutines.yield
 import org.videolan.medialibrary.interfaces.Medialibrary
 import org.videolan.medialibrary.interfaces.media.MediaWrapper
 import org.videolan.medialibrary.media.MediaLibraryItem
+import org.videolan.resources.SELECTED_ITEM
 import org.videolan.resources.util.HeadersIndex
 import org.videolan.television.R
 import org.videolan.television.databinding.SongBrowserBinding
@@ -70,7 +70,7 @@ import org.videolan.vlc.viewmodels.SortableModel
 import org.videolan.vlc.viewmodels.browser.TYPE_FILE
 import org.videolan.vlc.viewmodels.browser.TYPE_NETWORK
 import org.videolan.vlc.viewmodels.tv.TvBrowserModel
-import java.util.ArrayList
+import java.util.*
 
 private const val TAG = "MediaBrowserTvFragment"
 
@@ -101,6 +101,7 @@ abstract class BaseBrowserTvFragment<T> : Fragment(), BrowserFragmentInterface,
     private var inGrid = true
     protected var restarted = false
         private set
+    private var previouslySelectedItem:Int = 0
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         binding = SongBrowserBinding.inflate(inflater, container, false)
@@ -195,6 +196,18 @@ abstract class BaseBrowserTvFragment<T> : Fragment(), BrowserFragmentInterface,
                 override fun requestChildRectangleOnScreen(parent: RecyclerView, child: View, rect: Rect, immediate: Boolean) = false
 
                 override fun requestChildRectangleOnScreen(parent: RecyclerView, child: View, rect: Rect, immediate: Boolean, focusedChildVisible: Boolean) = false
+                override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
+                    super.onLayoutChildren(recycler, state)
+                    if (previouslySelectedItem != -1) {
+                        for (i in 0 until childCount) {
+                            if (i == previouslySelectedItem) {
+                                getChildAt(i)?.requestFocus()
+                                scrollToPosition(getPosition(getChildAt(i)!!))
+                                previouslySelectedItem = -1
+                            }
+                        }
+                    }
+                }
             }
             (gridLayoutManager as? GridLayoutManager)?.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                 override fun getSpanSize(position: Int): Int {
@@ -216,12 +229,31 @@ abstract class BaseBrowserTvFragment<T> : Fragment(), BrowserFragmentInterface,
                 }
             }
         } else {
-            gridLayoutManager = LinearLayoutManager(requireActivity())
+            gridLayoutManager = object : LinearLayoutManager(requireActivity()) {
+                override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
+                    super.onLayoutChildren(recycler, state)
+                    if (previouslySelectedItem != -1) {
+                        for (i in 0 until childCount) {
+                            if (i == previouslySelectedItem) {
+                                getChildAt(i)?.requestFocus()
+                                scrollToPosition(getPosition(getChildAt(i)!!))
+                                previouslySelectedItem = -1
+                            }
+                        }
+                    }
+                }
+            }
         }
         recyclerSectionItemGridDecoration.isList = !inGrid
         binding.list.layoutManager = gridLayoutManager
     }
 
+    override fun onPause() {
+        val lm = binding.list.layoutManager as LinearLayoutManager
+        previouslySelectedItem = lm.focusedChild?.let { lm.getPosition(it) } ?: 0
+        super.onPause()
+    }
+
 
     fun updateHeaders(it: HeadersIndex) {
         val headerItems = ArrayList<String>()



More information about the Android mailing list