RecyclerView实现双列表联动

转载自fatchao的博客

地址:http://www.jianshu.com/p/5864db231ed5

最近项目中需要实现一个分类页面

UI图

列表联动UI

实现要求

左侧联动右侧:

点击左侧列表的某一项,背景变色,同时右侧列表中对应的分类滚动到顶部

右侧列表悬停:

右侧列表滑动的时候相应的标题栏需要在顶部悬停

标题栏可点击

右侧联动左侧:

滚动右侧列表,监听滚动的位置,左侧列表需要同步选中相应的列表

效果图

列表联动效果图

对照着上面的UI要求,基本上实现了所有的需求,下面分享一下实现的思路

左侧联动右侧

两侧都是Recyclerview,一开始以为就是调用一下Recyclerview的scrollToPostion滚动到具体的位置就好,但是实际上并非如此,因为Recyclerview的滚动方法有两种

scrollToPosition(int)

但是实际上调用的时候就比较坑爹,分为两种情况

从上往下滚动

如果是从上往下滚动的时候,发现每次达不到预期的效果,只能将需要滚动的item的显示出来而已,并不能滚动到顶部

从下滚动

这种情况是OK的,每次能够达到想要的效果

scrollBy(int x,int y)

这个方法如果是针对LinearLayoutManager的话,可以动态计算滚动的高度,但是针对相对复杂的布局就非常麻烦,最后找到了一种解决方案:

滚动的position小于FirstVisibleItemPosition

直接调用scrollToPosition

mRv.smoothScrollToPosition(n);

滚动的position介于FirstVisibleItemPosition与LastVisibleItemPosition之间

获取需要滚动的position距离顶部的高度,然后调用scrollBy

inttop= mRv.getChildAt(n - firstItem).getTop();    mRv.smoothScrollBy(0,top);

滚动的position>LastVisibleItemPosition

先调用scrollToPosition将需要滚动的position显示出来,在滚动完成时进行监听,当滚动停止的时候,执行跟2中相同的操作,达到目的

整体代码如下

//通过滚动的类型来进行相应的滚动privatevoidsmoothMoveToPosition(intn){intfirstItem = mManager.findFirstVisibleItemPosition();intlastItem = mManager.findLastVisibleItemPosition();if(n <= firstItem) {            mRv.smoothScrollToPosition(n);        }elseif(n <= lastItem) {inttop = mRv.getChildAt(n - firstItem).getTop();            mRv.smoothScrollBy(0, top);        }else{            mRv.smoothScrollToPosition(n);            move =true;        }    }//监听第三种情况,滚动停止之后再次进行滚动privateclassRecyclerViewListenerextendsRecyclerView.OnScrollListener{@OverridepublicvoidonScrollStateChanged(RecyclerView recyclerView,intnewState){super.onScrollStateChanged(recyclerView, newState);if(move && newState == RecyclerView.SCROLL_STATE_IDLE) {                move =false;intn = mIndex - mManager.findFirstVisibleItemPosition();                Log.d("n---->", String.valueOf(n));if(0<= n && n < mRv.getChildCount()) {inttop = mRv.getChildAt(n).getTop();                    Log.d("top--->", String.valueOf(top));                    mRv.smoothScrollBy(0, top);                }            }        }@OverridepublicvoidonScrolled(RecyclerView recyclerView,intdx,intdy){super.onScrolled(recyclerView, dx, dy);        }    }

右侧列表悬停

之前有看过张旭童的关于利用itemDecoration来实现城市列表索引的博客,写的的确是挺好的,唯一遗憾的是itemDecoration实现的头部不支持点击,所以这里换了另外一种思路。

Sectioned实现方式

伪造一个头部,给一个标志,然后加入到已有的数据集合中,然后再Recyclerview的Adapter中针对此标志返回标题栏的布局,达到分组的目的

for (inti =0; i < data.length; i++) {SortBean titleBean = new SortBean(String.valueOf(i));titleBean.setTitle(true);//头部设置为true,默认为falsetitleBean.setTag(String.valueOf(i));mDatas.add(titleBean);for (intj =0; j < 10; j++) {SortBean sortBean = new SortBean(String.valueOf(i+"行"+ j +"个"));sortBean.setTag(String.valueOf(i));mDatas.add(sortBean);}        }  @Override    protected int getLayoutId(intviewType) {        return viewType ==0? R.layout.item_title : R.layout.item_classify_detail;}    @Override    public int getItemViewType(intposition) {        return list.get(position).isTitle() ?0:1;}

悬停的实现

其实这个利用了itemDecoration,调用RecyclerView.ItemDecoration的onDrawOver中进行绘制一个跟Title一模一样的标题栏就好了,这样就把第一个Section覆盖了,看起

来好像是悬停的感觉

当发现下一个title顶上来的时候,将canvas向上平移,产生一种向上挤压的动画效果

if(null!=tag&& !tag.equals(suspensionTag)) {if(child.getHeight() + child.getTop() < mTitleHeight) {                    c.save();                    flag =true;                    c.translate(0, child.getHeight() + child.getTop() mTitleHeight);                }            }

绘制悬停的头部

这里没有一个一个控件的进行绘制,因为单个绘制比较麻烦,所以直接绘制了整个布局,同时修改了布局中标题栏中的内容

View topTitleView = mInflater.inflate(R.layout.item_title,parent,false);        TextView tvTitle = (TextView) topTitleView.findViewById(R.id.tv_title);        tvTitle.setText("测试数据"+tag);//进行测量获取MeasureSpec:toDrawWidthSpec,toDrawHeightSpec,代码省略//依次调用 measure,layout,draw方法,将复杂头部显示在屏幕上。topTitleView.measure(toDrawWidthSpec, toDrawHeightSpec);        topTitleView.layout(parent.getPaddingLeft(),parent.getPaddingTop(),parent.getPaddingLeft() + topTitleView.getMeasuredWidth(),parent.getPaddingTop() + topTitleView.getMeasuredHeight());        topTitleView.draw(c);//Canvas默认在视图顶部,无需平移,直接绘制

标题栏可点击

由于是采用的布局而不是itemDecoration的实现,所以所有的标题栏都是可以点击跳转的

右侧联动左侧

当右侧悬停的title内容发生变化的时候,通过一个接口进行回调左侧列表即可,比较简单,贴下代码:

if(!Objects.equals(tag, currentTag)) {Log.d("tag---->",String.valueOf(MainActivity.finalNumber));            currentTag =tag;Integerinteger=Integer.valueOf(currentTag);            mCheckListener.check(integer,false);        }

Demo下载地址

作者:fatchao

链接:http://www.jianshu.com/p/5864db231ed5

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容