Fix fast-scroll bugs
Fix some behavior issues with the new fast scroll view.
This commit is contained in:
parent
0a18108419
commit
688f9d3a52
3 changed files with 19 additions and 10 deletions
|
@ -6,6 +6,7 @@ import android.util.AttributeSet
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.dynamicanimation.animation.DynamicAnimation
|
import androidx.dynamicanimation.animation.DynamicAnimation
|
||||||
|
@ -13,7 +14,6 @@ import androidx.dynamicanimation.animation.SpringAnimation
|
||||||
import androidx.dynamicanimation.animation.SpringForce
|
import androidx.dynamicanimation.animation.SpringForce
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.R
|
|
||||||
import org.oxycblt.auxio.databinding.ViewFastScrollBinding
|
import org.oxycblt.auxio.databinding.ViewFastScrollBinding
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.ui.Accent
|
import org.oxycblt.auxio.ui.Accent
|
||||||
|
@ -27,7 +27,7 @@ import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A view that allows for quick scrolling through a [RecyclerView] with many items. Unlike other
|
* A view that allows for quick scrolling through a [RecyclerView] with many items. Unlike other
|
||||||
* fast-scrollers, this one displays indicators instead of simply a scroll bar.
|
* fast-scrollers, this one displays indicators and a thumb instead of simply a scroll bar.
|
||||||
* This code is fundamentally an adaptation of Reddit's IndicatorFastScroll, albeit specialized
|
* This code is fundamentally an adaptation of Reddit's IndicatorFastScroll, albeit specialized
|
||||||
* towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/
|
* towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
|
@ -73,7 +73,8 @@ class FastScrollView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up this view with a [RecyclerView] and a corresponding [FastScrollThumb].
|
* Set up this view with a [RecyclerView]. [getItem] is called when the first character
|
||||||
|
* of a piece of data is needed.
|
||||||
*/
|
*/
|
||||||
fun setup(recycler: RecyclerView, getItem: (Int) -> Char) {
|
fun setup(recycler: RecyclerView, getItem: (Int) -> Char) {
|
||||||
check(mRecycler == null) { "Only set up this view once." }
|
check(mRecycler == null) { "Only set up this view once." }
|
||||||
|
@ -95,6 +96,7 @@ class FastScrollView @JvmOverloads constructor(
|
||||||
|
|
||||||
if (recycler.isAttachedToWindow && recycler.adapter != null) {
|
if (recycler.isAttachedToWindow && recycler.adapter != null) {
|
||||||
updateIndicators()
|
updateIndicators()
|
||||||
|
binding.scrollIndicatorText.requestLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide this view if there is nothing to scroll
|
// Hide this view if there is nothing to scroll
|
||||||
|
@ -147,17 +149,17 @@ class FastScrollView @JvmOverloads constructor(
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
performClick()
|
performClick()
|
||||||
|
|
||||||
val success = handleTouch(event.action, event.y.roundToInt())
|
val success = handleTouch(event.action, event.x.roundToInt(), event.y.roundToInt())
|
||||||
|
|
||||||
// Depending on the results, update the visibility of the thumb and the pressed state of
|
// Depending on the results, update the visibility of the thumb and the pressed state of
|
||||||
// this view.
|
// this view.
|
||||||
isPressed = success
|
|
||||||
binding.scrollThumb.isActivated = success
|
binding.scrollThumb.isActivated = success
|
||||||
|
binding.scrollIndicatorText.isPressed = success
|
||||||
|
|
||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleTouch(action: Int, touchY: Int): Boolean {
|
private fun handleTouch(action: Int, touchX: Int, touchY: Int): Boolean {
|
||||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||||
binding.scrollIndicatorText.setTextColor(inactiveColor)
|
binding.scrollIndicatorText.setTextColor(inactiveColor)
|
||||||
lastPos = -1
|
lastPos = -1
|
||||||
|
@ -166,7 +168,7 @@ class FastScrollView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to figure out which indicator the pointer has landed on
|
// Try to figure out which indicator the pointer has landed on
|
||||||
if (touchY in (binding.scrollIndicatorText.top until binding.scrollIndicatorText.bottom)) {
|
if (binding.scrollIndicatorText.isBeingPressed(touchX, touchY)) {
|
||||||
// Get the touch position in regards to the TextView and the rough text height
|
// Get the touch position in regards to the TextView and the rough text height
|
||||||
val indicatorTouchY = touchY - binding.scrollIndicatorText.top
|
val indicatorTouchY = touchY - binding.scrollIndicatorText.top
|
||||||
val textHeight = binding.scrollIndicatorText.height / indicators.size
|
val textHeight = binding.scrollIndicatorText.height / indicators.size
|
||||||
|
@ -211,4 +213,11 @@ class FastScrollView @JvmOverloads constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the pointer is currently in the view
|
||||||
|
*/
|
||||||
|
private fun View.isBeingPressed(x: Int, y: Int): Boolean {
|
||||||
|
return (x in (left until right) && y in (top until bottom)) || isPressed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
android:id="@+id/scroll_thumb"
|
android:id="@+id/scroll_thumb"
|
||||||
android:layout_width="@dimen/size_scroll_thumb"
|
android:layout_width="@dimen/size_scroll_thumb"
|
||||||
android:layout_height="@dimen/size_scroll_thumb"
|
android:layout_height="@dimen/size_scroll_thumb"
|
||||||
android:background="@drawable/ui_circle"
|
android:background="@drawable/ui_circular_button"
|
||||||
android:elevation="@dimen/elevation_small"
|
android:elevation="@dimen/elevation_small"
|
||||||
android:backgroundTint="?attr/colorPrimary"
|
android:backgroundTint="?attr/colorPrimary"
|
||||||
android:stateListAnimator="@animator/animator_thumb"
|
android:stateListAnimator="@animator/animator_thumb"
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/scroll_indicator_text"
|
android:id="@+id/scroll_indicator_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="@dimen/width_fast_scroll"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/inter_semibold"
|
android:fontFamily="@font/inter_semibold"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
<!-- Width Namespace | Width for UI elements -->
|
<!-- Width Namespace | Width for UI elements -->
|
||||||
<dimen name="width_track_number">32dp</dimen>
|
<dimen name="width_track_number">32dp</dimen>
|
||||||
<dimen name="width_thumb_view">50dp</dimen>
|
|
||||||
<dimen name="width_play_stroke">1dp</dimen>
|
<dimen name="width_play_stroke">1dp</dimen>
|
||||||
|
<dimen name="width_fast_scroll">18dp</dimen>
|
||||||
<dimen name="width_dialog_button_min">64dp</dimen>
|
<dimen name="width_dialog_button_min">64dp</dimen>
|
||||||
|
|
||||||
<!-- Size Namespace | Width & Heights for UI elements -->
|
<!-- Size Namespace | Width & Heights for UI elements -->
|
||||||
|
|
Loading…
Reference in a new issue