【问题标题】:RecyclerView, StaggeredGridLayoutManager Refresh BugRecyclerView, StaggeredGridLayoutManager 刷新 Bug
【发布时间】:2015-01-07 18:21:10
【问题描述】:

我使用了支持库 v7-21,但 RecyclerView 显示不正确。 GridLayoutManagerLinearLayoutManager 没问题。只有在StaggeredGridLayoutManager 中加载我的DataSet 然后刷新数据时才会出现问题。 数据刷新工作正常,但RecyclerView 的视图存在于屏幕之外。

有人知道怎么解决吗?

【问题讨论】:

  • 同样的事情发生在我身上...... :( StaggeredGridLayoutManager 到今天为止是错误的......

标签: android android-recyclerview staggered-gridview


【解决方案1】:

我发现的一个简单解决方案是,当您将适配器设置为回收站视图时,您必须再次设置布局管理器。

【讨论】:

    【解决方案2】:

    2015 年 1 月 4 日更新(底部)

    我在 https://github.com/dbleicher/recyclerview-grid-quickreturn 有一个示例项目来演示这一点。但这里还有一些细节可能会对您有所帮助。

    当您向 RecyclerView 添加/删除项目时,您应该调用 notifyItemInserted/notifyItemRemoved 让适配器告诉布局管理器重新布局受影响的视图。例如在适配器中:

    public void addItemAtPosition(int position, String item) {
        myDataset.add(position, item);
        mAdapter.notifyItemInserted(position);        
    }
    

    如果您调用此方法来添加视图,并且该视图在屏幕上,则 SGLM 似乎可以按预期工作,插入和调整布局。但是,如果您正在查看列表顶部并且在位置 0 处添加项目,则视图将在屏幕外创建(您将看不到它)。您可以使用以下代码滚动到该视图:

    public void addItemAtPosition(int position, String item) {
        myDataset.add(position, item);
        mAdapter.notifyItemInserted(position);
        mSGLM.scrollToPosition(position);
    }
    

    在 StaggeredGridLayoutManager 中存在(恕我直言)一个错误,该错误在“屏幕外”添加项目时会显示出来。根据 yiğit boyar 在此线程中的 cmets https://plus.google.com/u/1/111532428576115387787/posts/6xxayUBz2iV

    "...如果添加的项目越界,布局管理器不关心"

    这就是错误出现的地方。对于 SGLM,when 发生重新布局时存在时间问题。在我的示例代码(上面的链接)中,我有一个 ItemDecorator,它为最顶部的项目添加边距,因此它们不会被工具栏遮挡。使用上面的代码时,布局错误地在插入新项目时在屏幕上“向下”移动的项目上保留了此边距。无赖。

    这是在顶部添加之前的布局:

    这是在顶部添加项目后演示错误的布局:

    有一种解决方法,但它有点违背了使用 RecyclerView 的目的。基本上,如果您只是在添加/删除之后调用 notifyDataSetChanged,这将使 SGLM 使其整个布局无效。从效率的角度来看,这不是最佳的,但它确实会导致正确的布局。使用以下代码:

    public void addItemAtPosition(int position, String item) {
        myDataset.add(position, item);
        mAdapter.notifyDataSetChanged();  // Should NOT do this, but it works!
        mSGLM.scrollToPosition(position);
    }
    

    将产生正确的添加后布局:

    希望这会有所帮助。

    更新:2014-01-04

    如 cmets 中所述,另一种解决方法是在执行插入后在 recyclerview 上调用 invalidateItemDecorations()。现在,似乎在插入后立即这样做会忽略此调用(可能是因为布局传递已经在运行)。如果有人暂时推迟通话,它似乎确实有效:

    public void addItemAtPosition(int position, String item) {
        myDataset.add(position, item);
        mAdapter.notifyItemInserted(position);
        mSGLM.scrollToPosition(position);
    
        // Items added to the top row? Better invalidate the decorator.
        // Delay to ensure that the previous layout pass has completed.
        if (position < columnCount) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mRecycler.invalidateItemDecorations();
                }
            }, 300);
        }
    }
    

    【讨论】:

    • 物品装饰也会被缓存,因此除非物品无效,否则我们不会重新绑定它。你应该打电话给rv.invalidateItemDecorations
    • 当我在插入项目后调用 rv.invalidateItemDecorations() 时,调用被忽略,因为(我相信)从调用到 notifyItemInserted 的过程中已经有一个布局传递。如果有人延迟了对 invalidateItemDecorations() 的调用,这确实有效。所以,仍然存在一个“时机”问题,即何时使装饰无效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 2020-11-11
    相关资源
    最近更新 更多