开发瀑布流时,上下滑动列表,当手动滑到顶部时会出现瀑布流列表的顶部item出现交换的问题; 于是搜了很多的解决方式,大部分都是人云亦云,并无效果,最后还是看到一篇从源码级别分析此问题,因此解决了这个问题; 现记录一下:
为什么会出现交换位置和顶部留白呢, 看到一篇非常详细的原理分析博客,就不班门弄斧了,想要看原理 ,直接 瀑布流出现交换位置,顶部留白原理解析之传送门
简而言之,就是:
1.瀑布流需要每次onBindView时给imageview设置固定的宽高,当 每次向下滑动重用item时,全局刷新会清除mLazySpanLookup ,导致spanIndex无效, recyclerview填充布局只能重新计算spanIndex,然后后面会出现item之间交换的问题; 2.而添加了GapStrategy为GAP_HANDLING_NONE后, 因为瀑布流的item高度都是不一样的,重新排序之后,就不一定能够刚好把空间都占用,留出了顶部的空白。此时只是执行无动画的交换;
首先,大多数答案为 设置 瀑布流属性:
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//防止item 交换位置
仅仅 将原先的有动画交换item 变为无动画交换item; 囧~~
设置列表监听 不断的清除span; (错误方法) recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); layoutManager.invalidateSpanAssignments();//防止第一行到顶部有空白 } }); //StaggeredGridLayoutManager.class public void invalidateSpanAssignments() { this.mLazySpanLookup.clear(); this.requestLayout(); }并没有什么卵用, 并且滑动的时候不断的刷新布局,对性能也不好;
3.列表中添加数据使用 notifyItemRangeChanged 来刷新就可以解决了;