zoukankan      html  css  js  c++  java
  • 如何给RecyclerView加上滚动条--现在就教你

    时隔许久,我又要更博了,含蓄的话不多说了,今天我们的主题是这个RecyclerView。至于为什么要加个scrollBar?因为我的业务需求是需要一个实现成这样的,

    效果图:(可能看起来比较粗糙,但功能实现了,你可以自定义修改嘛~哈哈哈)

    可能我比较老派,我的app 中list的垂直布局还是喜欢用listView ,使用起来简单(可能博主我之前有个通用的adapter不舍得放弃吧,虽然RecyclerView也有通用的adapter,但总感觉显示简单的列表要多写几行代码,有点麻烦,哈哈哈,可能我就想偷懒吧)

    但既然今天的是这个RecyclerView那么我们就开始详细的说明下吧~废话不多说切入正题。

    注意:我这个View暂时只实现了垂直的View的ScrollBar的滚动,暂时没有横向实现,

    未来可能我会拓展,敬请期待吧(大佬可能觉得太简单,勿喷,求教,谢谢)

    先说下我的思路:

           一、初始思路(想一个新玩意总得有个过程和弯路嘛),可能跟你想法一样哦

    1.   用一个LinearLayout 布局套住 RecyclerView 和一个自定义的View  
    2. 自定义一个可以上下滚动的scrollBar 
    3. 滚动的ScrollBar绑定RecyclerView的滚动事件
    4. Ok

           二、现在的实现的思路 (我想了下如果用上面的方案实现的话就,必须写个xml文件,自定义一个ViewGroup,别人使用起来会很麻烦,当然你把他当成类库来用也很简单,而我就不想写xml)

    1. HobbyRecyclerView继承RecyclerView, 扩展这个功能
    2. 在HobbyRecyclerView 中先让子view的宽度缩小 ,留出给scrollBar的宽度
    3. 在HobbyRecyclerView中画一个ScrollBar ,这个bar的高度 = (view的可见高度 / view的所有子View的高度)* view可见高度 。
    4. 给HobbyRecyclerView加上滚动事件监听,监听滚动距离dy*(view的可见高度 / view的所有子View的高度)=  scrollbar 的滚动距离
    5. 给scrollBar加上监听,监听拖动距离转化为    RecyclerView的滚动距离   =   (scrollBar的拖动距离/scrollBar可滚动的区域高度(这里的区域高度等于View的高度)) * view的所有子View的高度 
    6. 测试ok

    思路也大概说了,那么就来看代码的实现吧。

    /**
     * @author mdm
     * @Description  HobbyRecyclerView
     * @Version 1.0
     */
    public class HobbyRecyclerView extends RecyclerView {
    
        private RectF mRangeRectf;
        private Paint mRangPaint;
        private int showMode = 1;
        //滚动条宽高
        private float scrollBarHeight;
        private float scrollBarWidth;
        //柱间隙
        private float scrollWidthSpace ;
        //滚动条宽度的等分比例
        private int scrollWidthWeight = 10;
        //Y轴的偏移值
        private float yScrollOffset = 0;
        //所有的子view的总高度 也就是这个
        private float childViewAllHeight;
        //可视区域的高度 其实这里就是View高度
        private float visualHeight;
        //可视区域的高度/所有的子view的总高度 得出的比例
        float range;
        //recyclerView的每个Item项的宽度
        private int childWidth;
        //判断触摸焦点
        private boolean isFocus = false;
    
        //手触摸时点的x,y坐标
        float x = 0;
        float y = 0;
    
        public HobbyRecyclerView(@NonNull Context context) {
            super(context);
        }
        public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init(context,attrs);
        }
        public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context,attrs);
        }
        /**
         * 初始化
         * @param context
         * @param attrs
         */
        private void init(Context context, AttributeSet attrs) {
            mRangeRectf = new RectF();
    //        region = new Region();
            mRangPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRangPaint.setStyle(Paint.Style.FILL);
            TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.HobbyRecyclerView);
            showMode = ta.getInteger(R.styleable.HobbyRecyclerView_scrollBarMode,1);
            ta.recycle();
            addOnScrollListener(onScrollListener);
        }
    
        @Override
        protected void onMeasure(int widthSpec, int heightSpec) {
            if(showMode != 1){
                int width = MeasureSpec.getSize(widthSpec);
                scrollBarWidth = width / scrollWidthWeight;//取10分之一
                scrollWidthSpace = scrollBarWidth / 10; //获取间隙
                childWidth = (int) (width - scrollBarWidth);
                scrollBarWidth = scrollBarWidth - 2 * scrollWidthSpace;
                for (int i = 0; i < getChildCount(); i++) {
                    measureChild(getChildAt(i),childWidth,heightSpec);
                    getChildAt(i).getLayoutParams().width = childWidth;
                }
                setMeasuredDimension(width,heightSpec);
            }else {
                super.onMeasure(widthSpec, heightSpec);
            }
    
        }
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
            visualHeight = getMeasuredHeight();
            childViewAllHeight = getChildAt(2).getHeight() * getAdapter().getItemCount();
            range = 0;
            if(childViewAllHeight != 0){
                range = visualHeight / childViewAllHeight;
            }
            scrollBarHeight = range * visualHeight;
        }
    
        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            drawRange(canvas);
        }
    
        private void drawRange(Canvas canvas){
            if(canvas == null) return;
            mRangeRectf.set(childWidth + scrollWidthSpace,yScrollOffset,childWidth + scrollBarWidth ,yScrollOffset + scrollBarHeight);
            if(isFocus) {
                mRangPaint.setColor(Color.parseColor("#2386BF"));
            }else{
                mRangPaint.setColor(Color.parseColor("#2EB3FF"));
            }
            canvas.drawRect(mRangeRectf,mRangPaint);
            Log.i("tag" , "yScrollOffset ------- " + yScrollOffset);
            Log.i("tag" , "scrollBarHeight ------- " + scrollBarHeight);
            Log.i("tag" , "yScrollOffset ------- " + yScrollOffset);
        }
    
    
        private RecyclerView.OnScrollListener onScrollListener = new 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);
                yScrollOffset += dy * range;
            }
        };
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    //获取屏幕上点击的坐标
                    x = event.getX();
                    y = event.getY();
                    if(x >= mRangeRectf.left
                            && x <= mRangeRectf.right
                            && y >= mRangeRectf.top
                            && y <= mRangeRectf.bottom){
                        isFocus = true;
                        invalidate();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(x >= mRangeRectf.left
                            && x <= mRangeRectf.right
                            && y >= mRangeRectf.top
                            && y <= mRangeRectf.bottom){
                        float diffValue = event.getY() - y;
                        scrollBy(0, (int) ((diffValue/visualHeight) * childViewAllHeight));
                        y = event.getY();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    isFocus = false;
                    invalidate();
                    break;
            }
            if(x >= childWidth
                    && x <= getMeasuredWidth()
                    && y >= 0
                    && y <= getMeasuredHeight()){
                return true;
            }else return super.onTouchEvent(event);
        }
    
    
        /**
         *  //当前RcyclerView显示区域的高度。水平列表屏幕从左侧到右侧显示范围
         int extent = this.computeHorizontalScrollExtent();
    
         //整体的高度,注意是整体,包括在显示区域之外的。
         int range = this.computeHorizontalScrollRange();
    
         //已经向下滚动的距离,为0时表示已处于顶部。
         int offset = this.computeHorizontalScrollOffset();
         */
    }

    是不是很简单呢?

    ok有什么问题自己看吧。如果你看到最后几行注释了,那么你会疑问,那是因为我看了这个文章 

    仿拼多多可水平滚动RecyclerView,自定义滚动条滚动距离

  • 相关阅读:
    Python之面向对象知识整理
    python2与python3的区别
    Gitlab 删除仓库文件夹
    Git撤销本地commit(未push)
    js库
    HTML | 打开网址后3秒跳转外链
    Vue CLI | 安装
    npm | npm淘宝镜像和查看镜像设置
    swiper | 过渡效果 effect: 'fade' 导致文字重叠
    CSS改变背景 | pattern.css
  • 原文地址:https://www.cnblogs.com/woaixingxing/p/10783104.html
Copyright © 2011-2022 走看看