快速滑動(dòng)條
默認(rèn)的效果就是不滾動(dòng)的時(shí)候不顯示,滾動(dòng)以后出現(xiàn)??梢允謩?dòng)拖動(dòng)滑塊實(shí)現(xiàn)快速滑動(dòng)。

app:fastScrollEnabled為true生效,這時(shí)候其他4個(gè)相關(guān)的Drawable缺一不可,否則異常
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_main"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:fastScrollEnabled="true"
app:fastScrollVerticalThumbDrawable="@drawable/state_thumb_test"
app:fastScrollVerticalTrackDrawable="@drawable/shape_track_bg"
app:fastScrollHorizontalThumbDrawable="@drawable/state_thumb_test"
app:fastScrollHorizontalTrackDrawable="@drawable/shape_track_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
看下源碼,里邊init的時(shí)候有判斷,4個(gè)drawable必須都有,否則拋出異常
mEnableFastScroller = a.getBoolean(R.styleable.RecyclerView_fastScrollEnabled, false);
if (mEnableFastScroller) {
StateListDrawable verticalThumbDrawable = (StateListDrawable) a
.getDrawable(R.styleable.RecyclerView_fastScrollVerticalThumbDrawable);
Drawable verticalTrackDrawable = a
.getDrawable(R.styleable.RecyclerView_fastScrollVerticalTrackDrawable);
StateListDrawable horizontalThumbDrawable = (StateListDrawable) a
.getDrawable(R.styleable.RecyclerView_fastScrollHorizontalThumbDrawable);
Drawable horizontalTrackDrawable = a
.getDrawable(R.styleable.RecyclerView_fastScrollHorizontalTrackDrawable);
initFastScroller(verticalThumbDrawable, verticalTrackDrawable,
horizontalThumbDrawable, horizontalTrackDrawable);
}
//4個(gè)drawable都必須有,ThumbDrawable可以是state狀態(tài),比如press為true和false顯示不同顏色的圖
void initFastScroller(StateListDrawable verticalThumbDrawable,
Drawable verticalTrackDrawable, StateListDrawable horizontalThumbDrawable,
Drawable horizontalTrackDrawable) {
if (verticalThumbDrawable == null || verticalTrackDrawable == null
|| horizontalThumbDrawable == null || horizontalTrackDrawable == null) {
throw new IllegalArgumentException(
"Trying to set fast scroller without both required drawables."
+ exceptionLabel());
}
Resources resources = getContext().getResources();
new FastScroller(this, verticalThumbDrawable, verticalTrackDrawable,
horizontalThumbDrawable, horizontalTrackDrawable,
resources.getDimensionPixelSize(R.dimen.fastscroll_default_thickness),
resources.getDimensionPixelSize(R.dimen.fastscroll_minimum_range),
resources.getDimensionPixelOffset(R.dimen.fastscroll_margin));
}
下邊只分析vertical滾動(dòng)條, 水平方向也一樣的道理
TrackDrawable: 就是那個(gè)背景條,寬度就是drawable的寬【水平方向滾動(dòng)那就是高了】,有個(gè)默認(rèn)的最小值8dp.
ThumbDrawable:就是那個(gè)可以拖動(dòng)的滑塊了
如果這兩個(gè)drawable的寬不一樣,那么左邊界就是大的那個(gè)來確定的,如下圖,我TrackDrawable寬度是25dp,ThumbDrawablek寬度是40dp

固定高度的滑塊
系統(tǒng)自帶的正常來說就可以的,可有人覺得數(shù)據(jù)太多的時(shí)候滑塊的高度太小了,想要一個(gè)固定高度的滑塊。
系統(tǒng)的是沒辦法了,因?yàn)椴]有對(duì)外提供可以修改的東西。
那咋辦了?
看了下系統(tǒng)滑塊就是一個(gè)ItemDecoration ,那我們把這個(gè)類復(fù)制下,完事稍微修改下滑塊高度不就行了
class FastScroller extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener
簡(jiǎn)單看下源碼
滑塊的位置以及大小由下邊2個(gè)變量決定的,所以搜一下這個(gè)兩個(gè)值是在哪里賦值的就行了,然后改掉
mVerticalThumbCenterY:滑塊的中心位置
mVerticalThumbHeight :滑塊的高度

系統(tǒng)代碼
if (mNeedVerticalScrollbar) {
float middleScreenPos = offsetY + verticalVisibleLength / 2.0f;
mVerticalThumbCenterY =
(int) ((verticalVisibleLength * middleScreenPos) / verticalContentLength);
mVerticalThumbHeight = Math.min(verticalVisibleLength,
(verticalVisibleLength * verticalVisibleLength) / verticalContentLength);
}
復(fù)制一下源碼,改動(dòng)下上邊這個(gè)地方就可以了
mVerticalThumbHeight=50;//固定高度
mVerticalThumbCenterY=mVerticalThumbHeight/2+(verticalVisibleLength-mVerticalThumbHeight)*offsetY/(verticalContentLength-verticalVisibleLength);
簡(jiǎn)單說下
| mVerticalThumbHeight/2 | 滑塊中心點(diǎn)的起始位置,滑塊高度的一半 |
| (verticalVisibleLength-mVerticalThumbHeight) | 滑塊可以移動(dòng)的距離,很明顯就是recyclerview的高度減去滑塊的高度 |
| offsetY/(verticalContentLength-verticalVisibleLength) | 當(dāng)前的偏移量除以總的可以移動(dòng)的距離,也就是比例了,從0到1,不要直接用額,要不都是int一除成0了,乘以1f 或者再前邊先乘以總量 |
用的時(shí)候很簡(jiǎn)單,代碼里直接new一個(gè)對(duì)象即可,里邊會(huì)自動(dòng)add進(jìn)去的
FastScroller2(
rv, verticalThumbDrawable, verticalTrackDrawable,
verticalThumbDrawable, verticalTrackDrawable,
resources.getDimensionPixelSize(R.dimen.fastscroll_default_thickness),
resources.getDimensionPixelSize(R.dimen.fastscroll_minimum_range),
resources.getDimensionPixelOffset(R.dimen.fastscroll_margin)
)
跟隨滑塊的懸浮窗
這個(gè)更簡(jiǎn)單了,滑塊背景的位置剛才分析過了,我們?cè)傩录觽€(gè)view在容器里,位置marginEnd滑塊寬度就行了,然后監(jiān)聽滾動(dòng)狀態(tài),讓它顯示并translateY就行了.
算出的progress就是滾動(dòng)的范圍,從0到1,和上邊固定滑塊邏輯一樣的。
然后你看下懸浮窗可以滾動(dòng)的范圍,乘以這個(gè)因子就行了.
addOnScrollListener(object :RecyclerView.OnScrollListener(){
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val range=recyclerView.computeVerticalScrollRange()
val offset=recyclerView.computeVerticalScrollOffset()
val progress=offset*1.0f/(range-recyclerView.height)
}
})