Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 7 additions & 80 deletions AnkiDroid/src/main/java/com/ichi2/anki/ui/RecyclerFastScroller.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import androidx.core.view.GravityCompat
import androidx.core.view.ViewCompat
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.ichi2.anki.utils.postDelayed
Expand Down Expand Up @@ -180,84 +181,6 @@ class RecyclerFastScroller
animator!!.start()
}
}

handle.setOnTouchListener(
object : OnTouchListener {
// The bar height when the drag started - used to handle bar resizing mid-drag
private var initialBarHeight = 0f

// The last touch Y position (in bar coordinates), adjusted for bar height changes
private var lastPressedYAdjustedToInitial = 0f
private var lastAppBarLayoutOffset = 0

override fun onTouch(
v: View,
event: MotionEvent,
): Boolean {
val recyclerView = requireNotNull(recyclerView) { "recyclerView" }
val recyclerViewAdapter = recyclerView.adapter
if (recyclerViewAdapter == null || recyclerViewAdapter.itemCount == 0) return false

onHandleTouchListener?.onTouch(v, event)
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
handle.isPressed = true
recyclerView.stopScroll()

var nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE
nestedScrollAxis = nestedScrollAxis or ViewCompat.SCROLL_AXIS_VERTICAL

recyclerView.startNestedScroll(nestedScrollAxis)

initialBarHeight = bar.height.toFloat()
lastPressedYAdjustedToInitial = event.y + handle.y + bar.y
lastAppBarLayoutOffset = appBarLayoutOffset
}
MotionEvent.ACTION_MOVE -> {
// Calculate touch position in bar coordinates
val newHandlePressedY = event.y + handle.y + bar.y
val barHeight = bar.height
// Adjust for any bar height changes since drag started
val newHandlePressedYAdjustedToInitial =
newHandlePressedY + (initialBarHeight - barHeight)

// Delta-based scrolling: scroll by the change in finger position,
// not the absolute position. This ensures the handle "sticks" to
// where the user grabbed it, rather than jumping
val deltaY = newHandlePressedYAdjustedToInitial - lastPressedYAdjustedToInitial
// Convert finger movement to scroll pixels:
// (finger movement / bar height) gives the proportion of the bar moved,
// multiply by scroll range to get pixels to scroll
val scrollPixels =
(
(deltaY / initialBarHeight) *
recyclerView.computeVerticalScrollRange()
).toInt()

try {
recyclerView.scrollBy(0, scrollPixels + lastAppBarLayoutOffset - appBarLayoutOffset)
} catch (e: Exception) {
Timber.w(e, "scrollBy")
}

lastPressedYAdjustedToInitial = newHandlePressedYAdjustedToInitial
lastAppBarLayoutOffset = appBarLayoutOffset
}
MotionEvent.ACTION_UP -> {
lastPressedYAdjustedToInitial = -1f

recyclerView.stopNestedScroll()

handle.isPressed = false
postAutoHide()
}
}

return true
}
},
)

translationX = hiddenTranslationX.toFloat()
}

Expand Down Expand Up @@ -390,8 +313,10 @@ class RecyclerFastScroller
// Retrieve the adapter to determine item count.
val adapter = recyclerView?.adapter ?: return false

if (adapter.itemCount == 0) return false

// Force the handle to be selected since the user is touching the track (the parent container) and not the handle itself.
handle.isSelected = true
handle.isPressed = true

// The valid scroll area is (height-handle.height), since the position of the handle is defined by it's top edge, we subtract it.
val scrollableHeight = height - handle.height
Expand All @@ -411,7 +336,9 @@ class RecyclerFastScroller
.coerceIn(0, adapter.itemCount - 1)

try {
recyclerView?.scrollToPosition(targetPosition)
(recyclerView?.layoutManager as? LinearLayoutManager)
?.scrollToPositionWithOffset(targetPosition, 0)
?: recyclerView?.scrollToPosition(targetPosition)
} catch (e: Exception) {
Timber.w(e, "scrollToPosition")
}
Expand Down
Loading