RecyclerView,StaggeredGridLayoutManager刷新Bug

时间:2014-11-11 08:50:19

标签: android android-recyclerview staggered-gridview

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

有谁知道如何修复它?

2 个答案:

答案 0 :(得分:9)

更新2015-01-04(底部)

我有一个示例项目,可以在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似乎按预期工作插入和调整布局。但是,如果您正在查看列表顶部并在零位置添加项目,则会在屏幕外创建视图(您将看不到它)。您可以使用以下代码滚动到此视图:

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

(IMHO)StaggeredGridLayoutManager中的一个错误,通过添加“屏幕外”项来显示。根据yiğitboyar在这篇帖子https://plus.google.com/u/1/111532428576115387787/posts/6xxayUBz2iV

中的评论
  

“......如果项目超出界限,布局管理员不在乎”

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

这是在顶部添加之前的布局: Layout before adding at top

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

有一种解决方法,但它在某种程度上违背了使用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);
}

将导致适当的后添加布局: Proper layout result

希望这有帮助。

更新时间:2014-01-04

如评论中所述,另一种解决方法是在执行插入后在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);
    }
}

答案 1 :(得分:1)

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