如何给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,自定义滚动条滚动距离

原文地址:https://www.cnblogs.com/woaixingxing/p/10783104.html

时间: 2024-10-10 17:41:23

如何给RecyclerView加上滚动条--现在就教你的相关文章

CSS 页面顶部阴影和给浏览器强制加上滚动条

/*给浏览器强制加上滚动条*/ html{height: 101%;} /*页面顶部阴影*/ body:before{ content: ""; position: fixed; top:-10px; left:0; width:100%; height:10px; -webkit-box-shadow: 0px 0px 10px rgba(0,0,0,.8); -moz-box-shadow: 0px 0px 10px rgba(0,0,0,.8); box-shadow: 0px

jQuery实现当拉动滚动条到底部加载数据

<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>jQuery实现当拉动滚动条到底部加载数据</title><script type="text/javascript&qu

Android Material Design学习之RecyclerView代替 ListView

前言 # Android Material Design越来越流行,以前很常用的 ListView 现在也用RecyclerView代替了,实现原理还是相似的.笔者实现一下 RecyclerView,代码比较简单,适合初学者,如有错误,欢迎指出. 源码地址(欢迎star) https://github.com/studychen/SeeNewsV2 本文链接 http://blog.csdn.net/never_cxb/article/details/50495505,转载请注明出处. 复习 L

谷歌下设置滚动条的css样式

.oLi-lists-scroll::-webkit-scrollbar { width:5px;  padding:1px; background:url(../images/repeat-bar.png) repeat-y;} /* Track */ .oLi-lists-scroll::-webkit-scrollbar-track {height:4px;} /* Handle */ .oLi-lists-scroll::-webkit-scrollbar-thumb { backgro

模拟滚动条控制内容滚动

每次页面内容超出范围的时候,为了美观,我们都会加上滚动条处理,要是浏览器默认滚动条无法满足美感的时候,我们需要自己模拟出一个符合需求的滚动条,如下: 实现过程: 1.简单样式: #div1 {width: 30px; height: 500px; background: black; position: absolute; left: 10px; top: 10px;}#div2 {width: 30px; height: 30px; background: red; position: abs

背景图100%出现滚动条时会有空白bug

.loginWrap { position:absolute;top: 0;left: 0;width:100%;height: 100%;} window.onresize = function(){ var widthOfMobile = $('#warpBackground'). outerHeight(); var withoutMargin = $('#mobileWarp'). outerHeight(); $('#mobileBg').css('height',widthOfMob

在RecyclerView列表滚动的时候显示或者隐藏Toolbar

先看一下效果: 本文将讲解如何实现类似于Google+应用中,当列表滚动的时候,ToolBar(以及悬浮操作按钮)的显示与隐藏(向下滚动隐藏,向上滚动显示),这种效果在Material Design 清单中有提到: "在合适的地方,当列表向下滚动,app bar可以退出屏幕,以便为内容区域留下更多的空间:而当列表向上滚动回来的时候,app bar又重新显示出来". 注:这里的向下滚动是指滚动到下面查看更多内容,相对应的手势操作其实是往上.同理向上滚动是指查看前面的内容,而手势其实是向下

IE6下出现横向滚动条问题的解决方案

当我们在css样式设置为html {overflow-y:auto;}时,在ie7以上版本应用时不会有问题,可是在ie6下就会发现垂直滚动条出现会引起横向滚动条出现.究其原因是在ie6下,当内容过多出现垂直滚动条时,此时页面的宽度为其本来宽度加上滚动条的宽度,导致页面宽度超过100%,而出现横向滚动条,在ie7+浏览器中,会自动的识别滚动条,页面宽度为内容的宽度加上滚动条的宽度等于100%,而不会出现滚动条,这相当于是ie的滚动条bug(纯属个人见解,不对的地方还请指出,共同学习交流). 解决上

Android Material Design系列之RecyclerView和CardView

去年很早之前,我就讲解过RecyclerView的使用,今天我们就在讲解CardView的时候,顺便再把RecyclerView同时讲解一下.RecyclerView.CardView为用于显示复杂视图的新增Widget.接下来看看如何使用吧. RecyclerView RecyclerView介绍 RecyclerView作为替代ListView使用,它更先进,更灵活,RecyclerView标准化了ViewHolder,ListView中convertView是复用的,在RecyclerVi