RecyclerView的fastScroll 快速滑動條 固定高度的滑塊 跟隨滑塊的懸浮窗

快速滑動條

默認的效果就是不滾動的時候不顯示,滾動以後出現。可以手動拖動滑塊實現快速滑動。


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)
                }
            })
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章