FormScrollHelper--标题和表格联合滚动

FormLayoutManager首页,里面有github地址

目录

前言

FormScrollHelper代码

TFormScrollHelper代码


前言

表格基本实现了,但表格顶部通常有个标题的横线列表跟着一起水平滚动,或是左侧有个垂直列表的标题跟着一起垂直滚动。有一个联合滚动的工具类FormScrollHelper在我封装的库里面,接下来就是要解说FormScrollHelper这个类。

FormScrollHelper代码

要用FormScrollHelper这个帮助类,前提是你的标题的列表必须也是用RecyclerView。代码只有几十行,用法可以参考demo的HFormActivity,VFormActivity和HVFormActivity。

        FormScrollHelper formScrollHelper = new FormScrollHelper();
        formScrollHelper.connectRecyclerView(mRecyclerView);
        formScrollHelper.connectRecyclerView(rvTopTitle);
        formScrollHelper.connectRecyclerView(rvLeftTitle);

上面的代码是HVFormActivity的代码,其实就是把几个RecyclerView都放进connectRecyclerView方法即可。而这个方法主要就是让RecyclerView设置一个mScrollListener,和把所有RecyclerView加到FormScrollHelper管理的一个列表里,所以我们主要还是看一下这个mScrollListener。

private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            // 以下场景处理的是,滑动过程中手指松开,移到另外一个recyclerview进行滚动
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                // 该recyclerview进入滚动状态的时候,其余四个要先停止滚动
                int currentIndex = mRecyclerViews.indexOf(recyclerView);
                for (int i = 0; i < mRecyclerViews.size(); i++) {
                    if (i != currentIndex) {
                        mRecyclerViews.get(i).stopScroll();
                    }
                }
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                // 手指所放在的当前recyclerview的下标
                int currentIndex = mRecyclerViews.indexOf(recyclerView);
                for (int i = 0; i < mRecyclerViews.size(); i++) {
                    if (i != currentIndex) {
                        mRecyclerViews.get(i).scrollBy(dx, dy);
                    }
                }
            }
        }
    };

先看onScrolled方法,这个方法里面拿到的recyclerView就是手指正在操作的列表,然后根据列表拿到该RecyclerView的下标。接着遍历列表让其他RecyclerView滚动相同的dx和dy,就OK了。

再看onScrollStateChanged,相信大家也猜到是干什么的了(因为有注释)。没错,就是当你滑动一个列表,手指松开的一刻,那个列表其实还会有一段滑动的fling距离。这时你的手指松开并且是移到另外一个列表进行滑动的时候,必须手指不触摸的所有RecyclerView停下来。要是它们不停下来,你同时又在滑动新触摸的那个列表时,表格跟标题列表就会错位。其实代码也很简单,就是拿到新触摸的RecyclerView下标,然后遍历RecyclerView列表让其他RecyclerView调用stopScroll停下来。

然后就说完了,就是这样,就可以实现几个RecyclerView的联合滚动。

TFormScrollHelper代码

这个帮助类是干什么的呢?可以看看demo的TFormActivity界面,如果你的业务跟金融期权有关,你可能了解到,有一种东西叫T型表。如下图的一个表:

但是这个帮助类,我没有封装在库里面,而是写在demo里面供大家参考一下。正所谓各花各眼,这个帮助类未必能符合你的需求,所以只给大家参考一下实现联动的思路方法。从TFormActivity可以看到用法如下:

        // 设置RecyclerView联动
        TFormScrollHelper scrollHelper = new TFormScrollHelper();
        scrollHelper.connectRecyclerView(rvLeftTitle, TFormScrollHelper.LEFT_AREA);
        scrollHelper.connectRecyclerView(rvLeftForm, TFormScrollHelper.LEFT_AREA);
        scrollHelper.connectRecyclerView(rvNum, TFormScrollHelper.CENTER_AREA);
        scrollHelper.connectRecyclerView(rvRightTitle, TFormScrollHelper.RIGHT_AREA);
        scrollHelper.connectRecyclerView(rvRightForm, TFormScrollHelper.RIGHT_AREA);

调用connectRecyclerView关联RecyclerView的同时,传入一个区域值,这个区域值只分为左中右。

    public void connectRecyclerView(RecyclerView recyclerView, int areaType){
        recyclerView.addOnScrollListener(mScrollListener);
        mViewIntegerMap.put(recyclerView, areaType);
    }

这次用一个map来保存所有的RecyclerView,而且是那RecyclerView来当key的。接下来也是看一下mScrollListener的代码。

private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            // 以下场景处理的是,滑动过程中手指松开,移到另外一个recyclerview进行滚动
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                // 该recyclerview进入滚动状态的时候,其余四个要先停止滚动
                for (RecyclerView view : mViewIntegerMap.keySet()){
                    if (view != recyclerView){
                        view.stopScroll();
                    }
                }
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                // 当前手指操作的区域
                int currentArea = mViewIntegerMap.get(recyclerView);
                for (RecyclerView view : mViewIntegerMap.keySet()){
                    if (view != recyclerView){
                        int areaType = mViewIntegerMap.get(view);
                        view.scrollBy(areaType == currentArea ? dx : -dx, dy);
                    }
                }
            }
        }
    };

看了上面那张演示图,可以发现垂直滚动是同方向一起滚的,但左右区域的列表水平的滚动方向是相反的。我们来看一下onScrolled的方法。先把当前操作的RecyclerView所在的区域currentArea拿到,然后也是遍历所有RecyclerView,除了正在触摸的RecyclerView以外其他RecyclerView都要调用scrollBy,重点是与之前不同的是,要调用scrollBy的那个RecyclerView如果与当前触摸区域不同的,传入的参数是 -dx。有人也许会有疑问,我在触摸左区域的列表,而中间区域的序号列表跟当前区域也不同啊,那它不就接收 -dx的滚动距离了吗。没错是的,不过中间那个列表只能垂直滚动,所以水平距离,我们传什么值都不会有影响。

而onScrollStateChanged里面的原理跟上一个帮助类说的一样,这里就不多说了。

发布了21 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/DNWalter/article/details/104050508