快速滑動條
默認的效果就是不滾動的時候不顯示,滾動以後出現。可以手動拖動滑塊實現快速滑動。
app:fastScrollEnabled爲true生效,這時候其他4個相關的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的時候有判斷,4個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個drawable都必須有,ThumbDrawable可以是state狀態,比如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滾動條, 水平方向也一樣的道理
TrackDrawable: 就是那個背景條,寬度就是drawable的寬【水平方向滾動那就是高了】,有個默認的最小值8dp.
ThumbDrawable:就是那個可以拖動的滑塊了
如果這兩個drawable的寬不一樣,那麼左邊界就是大的那個來確定的,如下圖,我TrackDrawable寬度是25dp,ThumbDrawablek寬度是40dp
固定高度的滑塊
系統自帶的正常來說就可以的,可有人覺得數據太多的時候滑塊的高度太小了,想要一個固定高度的滑塊。
系統的是沒辦法了,因爲並沒有對外提供可以修改的東西。
那咋辦了?
看了下系統滑塊就是一個ItemDecoration ,那我們把這個類複製下,完事稍微修改下滑塊高度不就行了
class FastScroller extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener
簡單看下源碼
滑塊的位置以及大小由下邊2個變量決定的,所以搜一下這個兩個值是在哪裏賦值的就行了,然後改掉
mVerticalThumbCenterY:滑塊的中心位置
mVerticalThumbHeight :滑塊的高度
系統代碼
if (mNeedVerticalScrollbar) {
float middleScreenPos = offsetY + verticalVisibleLength / 2.0f;
mVerticalThumbCenterY =
(int) ((verticalVisibleLength * middleScreenPos) / verticalContentLength);
mVerticalThumbHeight = Math.min(verticalVisibleLength,
(verticalVisibleLength * verticalVisibleLength) / verticalContentLength);
}
複製一下源碼,改動下上邊這個地方就可以了
mVerticalThumbHeight=50;//固定高度
mVerticalThumbCenterY=mVerticalThumbHeight/2+(verticalVisibleLength-mVerticalThumbHeight)*offsetY/(verticalContentLength-verticalVisibleLength);
簡單說下
mVerticalThumbHeight/2 | 滑塊中心點的起始位置,滑塊高度的一半 |
(verticalVisibleLength-mVerticalThumbHeight) | 滑塊可以移動的距離,很明顯就是recyclerview的高度減去滑塊的高度 |
offsetY/(verticalContentLength-verticalVisibleLength) | 當前的偏移量除以總的可以移動的距離,也就是比例了,從0到1,不要直接用額,要不都是int一除成0了,乘以1f 或者再前邊先乘以總量 |
用的時候很簡單,代碼裏直接new一個對象即可,裏邊會自動add進去的
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)
)
跟隨滑塊的懸浮窗
這個更簡單了,滑塊背景的位置剛纔分析過了,我們再新加個view在容器裏,位置marginEnd滑塊寬度就行了,然後監聽滾動狀態,讓它顯示並translateY就行了.
算出的progress就是滾動的範圍,從0到1,和上邊固定滑塊邏輯一樣的。
然後你看下懸浮窗可以滾動的範圍,乘以這個因子就行了.
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)
}
})