仅将 RecyclerView 中的视图动态添加到当前项目
Dynamically adding Views in a RecyclerView only to current item
我正在 RecyclerView
中为我的项目动态添加视图。这些添加的视图应该只与它们添加到的项目相关,但我在滚动时遇到了问题。似乎 View
被回收并加载了一个新项目,但是之前添加的视图仍然存在,只是现在在错误的项目上。
我假设这只是因为 ViewHolder
被重复使用,所以添加的项目在加载时再次显示为新项目。
如何解决这个问题?
您需要根据支持数据跟踪添加了哪些视图。我可能会在 onBindViewHolder()
中添加任何必要的额外视图,并删除 onViewRecycled()
中可能存在的任何视图。然后当你想让一个动态出现时,改变你跟踪它是否应该可见的任何变量,然后调用 notifyItemChanged()
.
每次添加新视图操作时,通过标签为具有新子项的项目保存信息。 (例如,在共享偏好中)
标记:在 BindViewHolder 上使用项目位置创建。
...
SharedPreference sharedPref = getSharedPreference("text" + position, context);
SharedPreference.Editor editor = sharedPref.edit();
editor.putString("view", "ImageView");
...
加载适配器时获取此值并将默认值设置为空。
我不确定它的效率,但我会工作。
...
String viewType = sharedPref.getString("view", null);
//it will return ImageView
如果您知道一些可能的视图类型,例如始终是 ImageView 和 TextView,那么使用一些 if 语句就可以了。
if(viewType.equals("ImageVIew")){
item(position).addView(new ImageVIew(context));
}
祝你好运
基于此:
but those previously added Views are still there, but now on the wrong item.
基本上,根据 RecyclerView 文档,您必须每次在 onBindViewHolder()
方法中重置视图,
这么说吧,你有一个方法可以设置一个 view param 如果它是你的个人资料,那么代码如下,
if (list.get(position).getId()==PreferenceManager.getUserID())
{
// do some view change here
setViewParam(true);
}else
{
// reset the view change here
setViewParam(false);
}
所以你在这里做的是给回收的 ViewHolder 一个重置的机会。
如果您需要帮助,请发表评论!
在您的 recyclerView
的适配器 class 中,
在 onBindViewHolder
方法中,
创建另一个适配器并为您的新适配器执行相同的方法。
层次结构将是,
mainRecyclerView -> item1(->childRecyclerView1) , item2(->childRecyclerView2), item3(->childRecyclerView3)
这样你就可以实现你想要的,而不会在错误的项目上看到错误的值。
你可以用这个! setItemViewCacheSize(int size)
在此处查看 RecyclerViewDocumentation。
The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.
您应该在您的子项目布局 XML
中采用任何空布局,例如 Linearlayout
,然后在滚动列表时以这种方式将视图添加到您的特定项目的 LinearLayout
中您添加到 LinearLayout
的子视图中的一些也会随着该项目滚动。
首先,你能再分享一些代码吗?
其次,为什么要动态添加新视图?为什么不使用不同的 VIEWTYPE,或者只是将这些视图放在布局上,然后将它们设为 visible/invisible 或 visible/gone? (相信这样效率会更高)
让我提醒你一些关于 RecyclerView 的事情,是的,当用户滚动时,viewHolder 正在被重用(很少有人可以创建,甚至超过它需要填满屏幕)。因此,如果您在 "item A" 上添加了一些视图并且用户滚动到 "item Z",则可以为该 "item Z" 重用该 viewHolder,因此会显示之前添加的视图。
你怎么解决这个问题?
如果您需要添加新视图,请始终检查每个项目,如果是,则添加它们(如果尚未添加),否则始终将这些视图(如果存在)删除到 return 默认 viewHolder 状态(或其他任何状态)你叫它)。
希望对您有所帮助。
这是我的一个老问题。它被悬赏,因此人气飙升,出现了多个新的和不相关的答案。
正如我对 的评论和 @CQM 在我的原始问题下方的评论中所述,答案是覆盖 onViewRecycled()
方法并在那里执行任何需要的操作。该方法在视图被回收时调用,任何清理操作都可以在这里完成。
可以找到有关此方法的文档 here。
就我而言,这是删除附加到视图的不可见 TextView
的问题。案文本身已被删除,但观点仍然存在。如果许多不可见的 TextView
堆积在视图上并且在滚动时没有正确回收,滚动将开始滞后。
我正在 RecyclerView
中为我的项目动态添加视图。这些添加的视图应该只与它们添加到的项目相关,但我在滚动时遇到了问题。似乎 View
被回收并加载了一个新项目,但是之前添加的视图仍然存在,只是现在在错误的项目上。
我假设这只是因为 ViewHolder
被重复使用,所以添加的项目在加载时再次显示为新项目。
如何解决这个问题?
您需要根据支持数据跟踪添加了哪些视图。我可能会在 onBindViewHolder()
中添加任何必要的额外视图,并删除 onViewRecycled()
中可能存在的任何视图。然后当你想让一个动态出现时,改变你跟踪它是否应该可见的任何变量,然后调用 notifyItemChanged()
.
每次添加新视图操作时,通过标签为具有新子项的项目保存信息。 (例如,在共享偏好中) 标记:在 BindViewHolder 上使用项目位置创建。
...
SharedPreference sharedPref = getSharedPreference("text" + position, context);
SharedPreference.Editor editor = sharedPref.edit();
editor.putString("view", "ImageView");
...
加载适配器时获取此值并将默认值设置为空。 我不确定它的效率,但我会工作。
...
String viewType = sharedPref.getString("view", null);
//it will return ImageView
如果您知道一些可能的视图类型,例如始终是 ImageView 和 TextView,那么使用一些 if 语句就可以了。
if(viewType.equals("ImageVIew")){
item(position).addView(new ImageVIew(context));
}
祝你好运
基于此:
but those previously added Views are still there, but now on the wrong item.
基本上,根据 RecyclerView 文档,您必须每次在 onBindViewHolder()
方法中重置视图,
这么说吧,你有一个方法可以设置一个 view param 如果它是你的个人资料,那么代码如下,
if (list.get(position).getId()==PreferenceManager.getUserID())
{
// do some view change here
setViewParam(true);
}else
{
// reset the view change here
setViewParam(false);
}
所以你在这里做的是给回收的 ViewHolder 一个重置的机会。 如果您需要帮助,请发表评论!
在您的 recyclerView
的适配器 class 中,
在 onBindViewHolder
方法中,
创建另一个适配器并为您的新适配器执行相同的方法。
层次结构将是,
mainRecyclerView -> item1(->childRecyclerView1) , item2(->childRecyclerView2), item3(->childRecyclerView3)
这样你就可以实现你想要的,而不会在错误的项目上看到错误的值。
你可以用这个! setItemViewCacheSize(int size)
在此处查看 RecyclerViewDocumentation。
The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.
您应该在您的子项目布局 XML
中采用任何空布局,例如 Linearlayout
,然后在滚动列表时以这种方式将视图添加到您的特定项目的 LinearLayout
中您添加到 LinearLayout
的子视图中的一些也会随着该项目滚动。
首先,你能再分享一些代码吗?
其次,为什么要动态添加新视图?为什么不使用不同的 VIEWTYPE,或者只是将这些视图放在布局上,然后将它们设为 visible/invisible 或 visible/gone? (相信这样效率会更高)
让我提醒你一些关于 RecyclerView 的事情,是的,当用户滚动时,viewHolder 正在被重用(很少有人可以创建,甚至超过它需要填满屏幕)。因此,如果您在 "item A" 上添加了一些视图并且用户滚动到 "item Z",则可以为该 "item Z" 重用该 viewHolder,因此会显示之前添加的视图。
你怎么解决这个问题?
如果您需要添加新视图,请始终检查每个项目,如果是,则添加它们(如果尚未添加),否则始终将这些视图(如果存在)删除到 return 默认 viewHolder 状态(或其他任何状态)你叫它)。
希望对您有所帮助。
这是我的一个老问题。它被悬赏,因此人气飙升,出现了多个新的和不相关的答案。
正如我对 onViewRecycled()
方法并在那里执行任何需要的操作。该方法在视图被回收时调用,任何清理操作都可以在这里完成。
可以找到有关此方法的文档 here。
就我而言,这是删除附加到视图的不可见 TextView
的问题。案文本身已被删除,但观点仍然存在。如果许多不可见的 TextView
堆积在视图上并且在滚动时没有正确回收,滚动将开始滞后。