RecyclerView的fastScroll

快速滑動(dòng)條

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


image.png

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


image.png

固定高度的滑塊

系統(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 :滑塊的高度


image.png

系統(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)
                }
            })
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容