Browse Source

Fix scroller getting dragged incorrectly in RTL (fixes #5496)

arkon 3 years ago
parent
commit
7c72d6cb7c
1 changed files with 50 additions and 2 deletions
  1. 50 2
      app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt

+ 50 - 2
app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt

@@ -1,11 +1,14 @@
 package eu.kanade.tachiyomi.widget
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.util.AttributeSet
 import android.view.MotionEvent
+import androidx.core.view.ViewCompat
 import eu.davidea.fastscroller.FastScroller
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.util.system.dpToPxEnd
+import eu.kanade.tachiyomi.util.system.isLTR
 
 class MaterialFastScroll @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
     FastScroller(context, attrs) {
@@ -14,14 +17,59 @@ class MaterialFastScroll @JvmOverloads constructor(context: Context, attrs: Attr
         setViewsToUse(
             R.layout.material_fastscroll,
             R.id.fast_scroller_bubble,
-            R.id.fast_scroller_handle
+            R.id.fast_scroller_handle,
         )
         autoHideEnabled = true
         ignoreTouchesOutsideHandle = true
     }
 
+    // Overridden to handle RTL
+    @SuppressLint("ClickableViewAccessibility")
     override fun onTouchEvent(event: MotionEvent): Boolean {
-        if (isHidden) return false
+        if (recyclerView.computeVerticalScrollRange() <= recyclerView.computeVerticalScrollExtent()) {
+            return super.onTouchEvent(event)
+        }
+
+        when (event.action) {
+            MotionEvent.ACTION_DOWN -> {
+                // start: handle RTL differently
+                if (
+                    if (context.resources.isLTR) {
+                        event.x < handle.x - ViewCompat.getPaddingStart(handle)
+                    } else {
+                        event.x > handle.width + ViewCompat.getPaddingStart(handle)
+                    }
+                ) return false
+                // end
+
+                if (ignoreTouchesOutsideHandle &&
+                    (event.y < handle.y || event.y > handle.y + handle.height)
+                ) {
+                    return false
+                }
+                handle.isSelected = true
+                notifyScrollStateChange(true)
+                showBubble()
+                showScrollbar()
+                val y = event.y
+                setBubbleAndHandlePosition(y)
+                setRecyclerViewPosition(y)
+                return true
+            }
+            MotionEvent.ACTION_MOVE -> {
+                val y = event.y
+                setBubbleAndHandlePosition(y)
+                setRecyclerViewPosition(y)
+                return true
+            }
+            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+                handle.isSelected = false
+                notifyScrollStateChange(false)
+                hideBubble()
+                if (autoHideEnabled) hideScrollbar()
+                return true
+            }
+        }
         return super.onTouchEvent(event)
     }