android 瀑布流 向下滑动出现交换位置,顶部空白

问题描述

开发瀑布流时,上下滑动列表,当手动滑到顶部时会出现瀑布流列表的顶部item出现交换的问题; 于是搜了很多的解决方式,大部分都是人云亦云,并无效果,最后还是看到一篇从源码级别分析此问题,因此解决了这个问题; 现记录一下:

问题原因

为什么会出现交换位置和顶部留白呢, 看到一篇非常详细的原理分析博客,就不班门弄斧了,想要看原理 ,直接 瀑布流出现交换位置,顶部留白原理解析之传送门

简而言之,就是:

1.瀑布流需要每次onBindView时给imageview设置固定的宽高,当 每次向下滑动重用item时,全局刷新会清除mLazySpanLookup ,导致spanIndex无效, recyclerview填充布局只能重新计算spanIndex,然后后面会出现item之间交换的问题;
2.而添加了GapStrategy为GAP_HANDLING_NONE后, 因为瀑布流的item高度都是不一样的,重新排序之后,就不一定能够刚好把空间都占用,留出了顶部的空白。此时只是执行无动画的交换;

过程

  1. 设置瀑布流属性 GapStrategy

首先,大多数答案为 设置 瀑布流属性:

layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//防止item 交换位置

仅仅 将原先的有动画交换item 变为无动画交换item; 囧~~

  1. 设置列表监听 不断的清除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 来刷新就可以解决了;

解决方法

  • 瀑布流中的item 通过layoutparams设置固定的大小
  • 设置GapStrategy
  • 添加数据使用notifyItemRangeChanged动态添加;
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐