Android RecyclerView LayoutManager重新排序问题
我试图在一个带有两列的Android RecyclerView LayoutManager重新排序问题,android,android-recyclerview,Android,Android Recyclerview,我试图在一个带有两列的StaggedGridLayoutManager的RecyclerView中显示三个项目(至少我有问题)。第一项跨越两行。下面是它的样子: 现在,我将项目“项目2”移到顶部。下面是我在适配器中调用的代码(这是我编写的一个示例,用于演示我在更复杂的项目中遇到的问题): private int findById(int id){ 对于(int i=0;i
StaggedGridLayoutManager的RecyclerView
中显示三个项目(至少我有问题)。第一项跨越两行。下面是它的样子:
现在,我将项目“项目2”移到顶部。下面是我在适配器中调用的代码(这是我编写的一个示例,用于演示我在更复杂的项目中遇到的问题):
private int findById(int id){
对于(int i=0;i
之后,数组就可以了:[项目2、项目1、项目3]
。然而,这一观点远非完美:
如果我触摸RecyclerView
(如果没有足够的项目滚动,足以触发overscroll效果),项目2移到左侧,我希望首先看到它(有一个漂亮的动画):
正如您可能在代码中看到的,我试图通过调用notifyDataSetChanged()
来替换notifyItemMoved(idx,position)
。它可以工作,但更改未设置动画
我写了一个完整的例子来证明这一点,并把它。这几乎是最小的(有移动项目和切换其范围的选项)
我看不出我做错了什么。这是StaggedGridLayoutManager的错误吗?我希望避免notifyDataSetChanged()
,因为我希望保持动画的一致性
编辑:经过一些挖掘,不需要一个完整的项目来显示问题。我拆下了整个跨度。当我尝试将项目2移动到位置0时,它不会移动:项目1在它之后移动,项目3在右侧移动,因此我有:空单元格、项目2、新行、项目1、项目3。我仍然有正确的布局后,滚动
更有趣的是,我没有使用GridLayoutManager
的问题。我需要一个完整的项目,所以它不是一个解决方案,但我想它确实是StaggedGridLayoutManager
中的一个错误。…我没有完整的答案,但我可以向您指出解决方法和错误报告(我相信是相关的)
更新布局使其看起来像您的第二个屏幕截图的诀窍是,在调用notifyItemMoved()
后,在StaggedGridLayoutManager
(sglm)上调用invalidateSpanAssignments()
。“挑战”是如果在nIM()之后立即调用它,它将不会运行。如果你把电话延迟几毫秒,它会的。因此,在MainActivity的参考代码中,我将您的sglm
设置为一个私有字段:
private StaggeredGridLayoutManager sglm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new Adapter();
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
sglm = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(sglm);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
}
在开关块中,在处理程序中引用它:
case R.id.move_sec_top:
adapter.moveItem(2, 0);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
sglm.invalidateSpanAssignments();
}
}, 100);
return true;
结果是动画仍在运行,布局以您想要的方式结束。这是一个真正的难题,但它确实有效。我相信这与我在以下链接中发现并报告的错误相同:
虽然我的“症状”和要求的电话不同,但根本问题似乎是相同的
祝你好运
编辑:无需延迟发布,只需发布即可:
case R.id.move_sec_top:
adapter.moveItem(2, 0);
new Handler().post(new Runnable() {
@Override
public void run() {
sglm.invalidateSpanAssignments();
}
});
return true;
我最初的理论是,在布局传递结束之前,呼叫一直被阻止,但我认为情况并非如此。相反,我现在认为,如果您立即调用invalidateSpanAssignments()
,它实际上执行得太快(在布局更改完成之前)。因此,上面的帖子(毫不延迟)只是将调用添加到渲染队列的末尾,在布局之后调用就发生在那里。我已经这样做了
StaggeredGridLayoutManager gaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
gaggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
dataList = YourDataList (Your Code for Arraylist);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerAdapter = new DataAdapter(dataList, recyclerView);
recyclerView.setAdapter(recyclerAdapter);
// Magic line
recyclerView.addOnScrollListener(new ScrollListener());
为自定义回收视图滚动侦听器创建类
private class ScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
gaggeredGridLayoutManager.invalidateSpanAssignments();
}
}
希望这能对您有所帮助。我不知道这是否是一个bug,但我也看到了这一点,当您滚动时,事情似乎在移动,gap策略
正在运行checked@tyczj:GAP\u HANDLING\u NONE
避免移动项目,但我仍然得到不正确的处理<代码>间隔\u处理\u移动\u项目\u在\u跨度之间\u
可能是默认设置,无论如何,我的行为与未指定任何内容的情况相同。是的,我知道我只是说,在滚动适配器检查间隔后,然后将项目移动到正确的位置听起来是一个合理的解释。我明天去看看,谢谢!谷歌已经承认了这个错误:你的解决方案在这段时间内工作得很好,所以我接受这个建议。关于如何使跨度分配失效动画化,有什么想法吗?谷歌花了很长时间来解决这个问题。。。现在,这个布局管理器已经不可用了。@mato我不太清楚你所说的“设置跨度分配无效动画”是什么意思?我所看到的是,只要使用处理程序/后期解决方案(如上所述),就会发生适当的布局事件和动画。你是在问,当项目的跨度计数发生变化时,是否可以控制项目增长/收缩的持续时间?谢谢,但是谷歌已经在支持库22和更新版本中发布了修复程序。现在,它与我在原始问题中编写的代码一起开箱即用。
private class ScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
gaggeredGridLayoutManager.invalidateSpanAssignments();
}
}