欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义RecyclerView的scrollbar

程序员文章站 2022-05-29 16:25:27
...

需求确定

自定义RecyclerView的scrollbar
在顶部RecyclerView的下面有一个蓝色的scrollbar,灰色区域代表整个RecyclerView,蓝色区域代表当前显示位置。

直接上代码

public class RecyclerViewSlidingBar extends View {

    private Paint allPaint, inPaint;
    private float mRoundRadius = 0;
    private RectF mViewRect, mInRect;
    private int viewWidth;
    private int viewHeight;
    private boolean canShow = false;

    public RecyclerViewSlidingBar(Context context) {
        this(context, null);
    }

    public RecyclerViewSlidingBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecyclerViewSlidingBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        allPaint = new Paint();
        allPaint.setAntiAlias(true); // 抗锯齿
        allPaint.setDither(true); // 防抖动
        allPaint.setColor(Color.parseColor("#FFD4D7DD"));
        allPaint.setStyle(Paint.Style.FILL);
        inPaint = new Paint();
        inPaint.setAntiAlias(true); // 抗锯齿
        inPaint.setDither(true); // 防抖动
        inPaint.setColor(Color.parseColor("#FF1DA1FF"));
        inPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        viewWidth = getWidth();
        viewHeight = getHeight();
        mViewRect = new RectF(0, 0, viewWidth, viewHeight);
        mRoundRadius = viewHeight / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (canShow) {
            canvas.drawRoundRect(mViewRect, mRoundRadius, mRoundRadius, allPaint);
            canvas.drawRoundRect(mInRect, mRoundRadius, mRoundRadius, inPaint);
        }
    }

    private float rvWidth;
    private float rvViewWidth;
    private float pointWidth;
    private float scroll;
    private float coefficient;

    public void bindRecyclerView(final RecyclerView mRv) {
        mRv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Log.e("onGlobalLayout", "onGlobalLayout");
                rvWidth = mRv.computeHorizontalScrollRange();
                rvViewWidth = mRv.getWidth();
                canShow = rvWidth > rvViewWidth;
                if (!canShow) return;
                coefficient = viewWidth / rvWidth;
                pointWidth = rvViewWidth / rvWidth * viewWidth;
                mInRect = new RectF(0, 0, pointWidth, viewHeight);
                invalidate();
                mRv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                mRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                        super.onScrollStateChanged(recyclerView, newState);
                    }

                    @Override
                    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                        super.onScrolled(recyclerView, dx, dy);
                        Log.e("onScrolled", dx + ":" + rvWidth);
                        if (dx != 0) {
                            scroll = coefficient * dx;
                            mInRect.left += scroll;
                            mInRect.right += scroll;
                            invalidate();
                        }
                    }
                });
            }
        });
    }
}

使用

在RecyclerView设置数据后调用bindRecyclerView()方法。

拓展

需求有个地方是和这个RecyclerView有关的,8个以下的时候从上到下,从左到右配排序,超过8的时候多出item向右延伸,然后从上到下排,前8个不变。

 if (mListAction.size() > 8) {
            manager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL);
            Collections.swap(mListAction, 1, 2);
            Collections.swap(mListAction, 1, 4);
            Collections.swap(mListAction, 3, 6);
            Collections.swap(mListAction, 3, 5);
        } else {
            manager = new GridLayoutManager(getActivity(), 4);
        }

我是这么做的,少于8个使用GridLayoutManager,实现前8个的排序方案,多于8个使用使用StaggeredGridLayoutManager,通过List位置交换,达到8个以上的排序方案。

相关标签: 自定义控件