引文:

之前在写一个stickScrollView的时候对不少人有一定的启示作用,这次针对stickScrollView再实现双列表的联动效果,希望对后续的开发者要实现同样的效果能有一定的启示,在实现的思路上比较简单,但是期间碰到了性能的问题,也会针对我优化的过程中提出自己优化的思路,让后面有遇到类似的问题的伙伴少走点弯路。

一.首先贴下效果图吧:

如图的效果图是左边列表点击之后,会滚动到左列表对应的右边字类目列表;当滑动右边的列表的时候,又可以反过来作用于左边列表,实现勾选上对应的左边列表。

1.实现思路,当左边列表点击的时候执行下面的代码:

 mLlRight.scrollToPositionWithOffset(scrollIndex, 0);//scrollIndex就是根据左边的点击项,计算右边滑动的位置

网上一直有思路是根据滑动的postion是否在第一个可见的item之前,可见item之后和最后可见item之后,最后的可见item之前三种情况来处理:

   if (scrollIndex <= firstItem) {//当要置顶的项在当前显示的第一个项的前面时mChildRecyclerviewRight.smoothScrollToPosition(scrollIndex);} else if (scrollIndex <= lastItem) {//当要置顶的项已经在屏幕上显示时,计算它离屏幕原点的距离int top = mChildRecyclerviewRight.getChildAt(scrollIndex - firstItem).getTop();mChildRecyclerviewRight.smoothScrollBy(0, top);} else {//当要置顶的项在当前显示的最后一项的后面时mChildRecyclerviewRight.smoothScrollToPosition(scrollIndex);//记录当前需要在RecyclerView滚动监听里面继续第二次滚动move = true;}

但是我发现这样的处理的话,能实现右边的定位的效果,但是走else判断的时候会触发右边列表的二次滚动,这个会触发右边列表的监听事件,类似手指滑动右边又重新进行左边的定位,虽然做了各种判断,但是在我的暴力测试下,还是会有这样的情况出现,很头疼,经测试还是LiearLayoutManager的方法比较靠谱。
### 2.当右边的列表滑动的时候,给recyclerview设置滚动监听就可以了:

    @Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);//在这里进行第二次滚动(最后的距离)if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {if (!mIsLeftTouch) {leftLocation();}}}

二.功能实现了,那现在咱们就谈谈性能问题了?

在真实情况是每个fragment的右侧列表数据都会很庞大,我们以前在列表上面可以用分页,但是现在必须一次性加载这么多数据,会出现以下的几个问题,针对这几个问题,我自己有进行优化,因此将优化的方案也贴出来,旨在希望大家不仅能开发功能性的app,还要开发出性能高的app,我现在是用了700条数据进行测试,每个item有图片和文案。没优化之前的使用是这个体验,启动是4s,如下图:

2.1因为这个界面的tab上面有角标,这个时候通常的做法,是在网络数据请求完成之后,再去进行ViewPager和TabLayout的初始化?

解决办法:我们在Activity加载的时候,我们就应该对viewPager,fragment初始化好,在网络请求拿到数据之后,我们只需要拿到初始化的fragment和tabLayout进行刷新数据就可以了。如下面就是在网络请求完成之后,回调fragment提供的接口的notifyDataChange方法,执行fragment刷新界面,同时我们对tablayout取到每一个需要赋值的view,进行设值,代码如下:

private void initVP() {for (FragmentWithTitleBean fragmentWithTitleBean : mFragments) {((CheckListFragment) (fragmentWithTitleBean.getFragment())).notifyDataChange();}//通知tablayout进行改变for (int i = 0, size = mOrderManagerTabs.getTabCount(); i < size; i++) {TabLayout.Tab tab = mOrderManagerTabs.getTabAt(i);if (tab != null && tab.getCustomView() != null) {TextView tvNum = tab.getCustomView().findViewById(R.id.tv_num);int intNum = 0;if (i == 0)intNum = getCheckInfoBean().getItemAllCount();else if (i == 1)intNum = getCheckInfoBean().getItemDoneCount();else if (i == 2)intNum = getCheckInfoBean().getItemAllCount() - getCheckInfoBean().getItemDoneCount();setTabNum(tvNum, intNum);}}}

2.2这么多的数据一次性设置给右侧的recyclerView,加载肯定会很慢?

RecycerlView在加载的时候,有这样的机制,如果是height为wrap_content的话,那么你的recyclerview在加载的时候,会一次性将所有数据加载进来?what fuck,那这样1000条数据同时设置,那不是卡爆了?但是当我们给recyclerview设置指定的高度的话,那么它一开始只会加载只需要显示的View,这样不管数据多少条,那也会好很多,那这样有思路,那么我们接下来就是要给右侧的recyclerview设定指定的高度:

private void initRightRVHeight() {mChildRecyclerviewRight.post(new Runnable() {@Overridepublic void run() {ViewGroup.LayoutParams layoutParams = mChildRecyclerviewRight.getLayoutParams();layoutParams.height = mParentActivity.getVpHeight();mChildRecyclerviewRight.setLayoutParams(layoutParams);}});}

2.3三个tab下面的fragment都有这么大的数据,都加载,cpu会有点吃力吧?没错就是这样!

那这样的话,就需要用到业内的懒加载机制,相信很多人都会有解决方案,这里我就贴下我的代码实现吧:

public abstract class LazyFragment extends Fragment {boolean isViewPrepared; // 标识fragment视图已经初始化完毕boolean hasFetchData; // 标识已经触发过懒加载数据@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);if (isVisibleToUser) {//当当前为显示页面时lazyFetchDataIfPrepared();}}@Overridepublic void onViewCreated(View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);isViewPrepared = true;}@Overridepublic void onActivityCreated(@Nullable Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);lazyFetchDataIfPrepared();}void lazyFetchDataIfPrepared() {// 用户可见fragment && 没有加载过数据 && 视图已经准备完毕if (getUserVisibleHint() && !hasFetchData && isViewPrepared) {hasFetchData = true; //已加载过数据lazyFetchData();}}abstract void lazyFetchData();
}

三.总结

经过上面三步之后,你再使用过的时候,就会有第一张图的体验了,真是快太多了呀,从原来的4s到现在的1s开,而且滑动也明显流畅了。

代码已经上传,有需要的可以去看下,github地址,您的点赞或者star是我持续开源的最大动力。

Android双列表联动和固定头部ScrollView效果实现相关推荐

  1. RecyclerView双列表联动

    双列表联动效果如下: 以上,是博主根据鸿洋大神的玩Android开放的API做的一个客户端,其中导航界面使用了双列表联动来展示数据. 一.前期基础知识储备 1.使用强大的开源项目BRVAH装载两个列表 ...

  2. Midnight.js – 实现奇妙的固定头部切换效果

    Midnight.js 是一款 jQuery 插件,在页面滚动的时候实现多个头设计之间的切换,所以你总是有一个头与它下面的内容层叠,看起来效果很不错. Midnight.js 可以让你轻松实现这种切换 ...

  3. Android股票列表联动

    使用ScrollerView+RecycleView实现股票列表联动效果:一个可以拿来可以直接使用的解决方案,而且滑动流畅,带标题栏悬浮功能,支持整行的点击效果,支持长安事件: 效果如下图所示: 实现 ...

  4. Android 仿京东淘宝拼多多的商品分类,双列表联动,RecyclerView嵌套

    淘宝京东的相对简单很多,两个RecyclerView就可实现了. 现在要做的是右边滑动的时候左边跟着联动,如下图: 思路:左右肯定都是RecyclerView了,至于中间的图片嘛当然也是Recycle ...

  5. 仿饿了么,百度外卖这些App的双ListView列表联动效果

    仿饿了么,百度外卖这些App的双列表联动效果 思路: 1.自定义一个悬浮条目且带移动替换效果的ListView. 2.在界面中左边是个普通的ListView,右边是我们自定义带效果的ListView. ...

  6. Android实现平板的类股票列表联动

    最近遇到了一个很恶心的问题,要实现类似于股票列表联动的问题,一般手机上基本用不着,这个效果一般用在平板上,要是手机上用这种效果那就没得聊了,我只能呵呵了... 下面开始正题部分,先上效果图,便于理解: ...

  7. Android 双u盘方案

     1      L1813系统上双U盘设计方案--系统设计 1.1     方案背景 Android原生的磁盘管理方案,设计的思想是将EMMC上的空间通过sdcard的server模拟成一个Sto ...

  8. Android项目实战(二十):浅谈ListView悬浮头部展现效果

    Android项目实战(二十):浅谈ListView悬浮头部展现效果 原文:Android项目实战(二十):浅谈ListView悬浮头部展现效果 先看下效果:需求是 滑动列表 ,其中一部分视图(粉丝数 ...

  9. 平板电脑Viewpad10安装win7与Android双系统

    注意事项: 1,  ViewPad10内置16GB SSD硬盘,其出厂时预分两个分区,分别为2G(预留给android系统) 以及 13G(预留给Win7系统)左右大小,建议用户不要破坏其原有分区大小 ...

最新文章

  1. AtomicInteger
  2. Linux上在文件夹上层新建一个同名目录
  3. 【转】WSS3.0开发--你还在为写CAML痛苦吗?
  4. 项目管理办公室 PMO
  5. ekf pose使用方法 ros_【百川小课堂】第13课—ROS学习(二)
  6. Linux驱动段错误,linux驱动调试--段错误之oops信息分析
  7. 命令行安装DHCP服务器
  8. 在AD中安装元件和封装库
  9. 上位机、下位机、单片机的关系
  10. 用matlab数学建模报告,Matlab数学建模实验报告.doc
  11. List异常报错:list All elements are null
  12. php union用法,php编程SQL语句union all的使用编程
  13. 联想Y460 XP下独显叹号
  14. 计算机专业必读哪两本经典书籍?
  15. 【Linux系统达梦数据库软件安装】
  16. Python第3章 流程控制
  17. 大家都来学 Java(一)快乐入门
  18. 杂谈——什么是Google Fuchsia ?
  19. rda分析怎么做_R语言做冗余分析(RDA)的一个简单小例子
  20. 常见存储介质介绍以及SD卡启动系统方法

热门文章

  1. Linux 环境变量 /etc/profile 和 ~/.bashrc
  2. c++进阶---IO类的详细介绍(一)
  3. 计算机网络:05---网络类型:局域网、城域网、广域网、个域网、无线网络
  4. java对象复制到另一个对象中_spring: beanutils.copyproperties将一个对象的数据塞入到另一个对象中(合并对象)...
  5. 同一类的不同对象,在调用相同的成员函数时,入口地址是相同的
  6. 概率论-1.3 概率的性质(重点:可列与极限之间的互相转换)
  7. 8086CPU常见汇编指令、debug命令
  8. OpenVINO 从yml处提取model下载链接,以mobile-ssd为例
  9. struct和class之间问题(+引发的个人思考,和对共用体思考)
  10. 计算机组成微程序设计,微程序设计