StaggeredGridLayoutManager 瀑布流返回顶部时跳跃问题 解决办法

在RecyclerView使用StaggeredGridLayoutManager实现瀑布流时,因onBindViewHolder()重新生成高度导致滚动回顶部时出现跳跃现象。解决方法是维护一个itemHeightList存储item高度,并在刷新时直接获取已记录的高度。如果有加载更多,设置StaggeredGridLayoutManager的gapStrategy为GAP_HANDLING_NONE避免问题。

       使用RecyclerView搭配StaggeredGridLayoutManager实现瀑布流时,一般会在Adapter的onBindViewHolder()方法里给每一个item随机生成一个高度,使得item的排布错落有致,不死板。但是当我们下拉到底部之后,上拉的时候,每一个item又会执行一遍onBindViewHolder()方法,这时如果还是简单随机给一个高度,由于每个item的高度都与之前的高度不一致,会导致我们滑回到顶部的时候,瀑布流的几个流可能不是平齐的,StaggeredGridLayoutManager会调整排布顺序,使得几个流的顶部平齐,产生了跳跃的现象。

       解决办法,在Adapter中维护一个记录每个item高度的itemHeightList,第一次填充时随机生成高度,在第二次填充的时候,直接去itemHeightList中取得对应位置的item高度,这样,回到顶部时,几个流就是正好平齐的了。

       但是当我们的瀑布流RecycrView中有拉到底部加载更多的逻辑的时候,每次加载了新的数据,又会产生跳跃问题。

       解决办法,给StaggeredGridLayoutManager 的setGapStrategy方法设成GAP_HANDLING_NONE,这样setAutoMeasureEnabled方法就会被置位false。

/**
     * Sets the gap handling strategy for StaggeredGridLayoutManager. If the gapStrategy parameter
     * is different than the current strategy, calling this method will trigger a layout request.
     *
     * @param gapStrategy The new gap handling strategy. Should be
     *                    {@link #GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS} or {@link
     *                    #GAP_HANDLING_NONE}.
     * @see #getGapStrategy()
     */
    public void setGapStrategy(int gapStrategy) {
        assertNotInLayoutOrScroll(null);
        if (gapStrategy == mGapStrategy) {
            return;
        }
        if (gapStrategy != GAP_HANDLING_NONE &&
                gapStrategy != GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS) {
            throw new IllegalArgumentException("invalid gap strategy. Must be GAP_HANDLING_NONE "
                    + "or GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS");
        }
        mGapStrategy = gapStrategy;
        setAutoMeasureEnabled(mGapStrategy != GAP_HANDLING_NONE);//看这里看这里看这里
        requestLayout();
    }
        所以只要

layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                layoutManager.invalidateSpanAssignments(); //防止第一行到顶部有空白区域
            }
        });

      亲测有效。

   

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值