我使用RecyclerView和CardView显示卡片列表。每张卡都有2个linearLayout(标题为1,扩展为1,第二张只有在按下卡时才可见)。
当我修改卡片的优先级时,卡片会移动到列表的新位置(我更改它在"阵列中的位置"项目,然后调用适配器。 notifyItemMoved(oldPosition,newPosition))它工作正常,我还调用了RecyclerView.scrollToPosition(newPosition)来显示列表中的新位置。
现在问题是,我想在我将它移动到新位置后扩展卡并且这样做我需要卡内的linearLayout,它们位于持有卡的ViewHolder中。我试图使用RecyclerView.findViewHolderAtPosition(newPosition),但只有当卡片显示在" scrollTo"之前我看到的地方时才返回ViewHolder,如果卡片被移出这些&# 34;可见卡"它总是返回null。 (我也使用mRecyclerView.setItemViewCacheSize(myDataset.size())来解决其他问题,所以即使它没有在视觉中,我也期待正确的ViewHolder)
public void moveTask(int oldPosition, int position, Task task) {
if (oldPosition < position) {
myDataset.add(position, task);
myDataset.remove(oldPosition);
} else {
myDataset.remove(oldPosition);
myDataset.add(position, task);
}
mAdapter.notifyItemMoved(oldPosition, position);
mAdapter.notifyDataSetChanged();
mRecyclerView.smoothScrollToPosition(position);
MyViewHolder holder =(MyViewHolder)mRecyclerView.findViewHolderForPosition(position);
mAdapter.expandCard(holder);
}
mAdapter.notifyDataSetChanged()不应该被调用(notifyItemMoved应该足够了)但有时没有它就行不通。
expandCard只是设置了linearLayout的可见性&#34;可扩展&#34;可见和其他linearLayout&#34;可扩展&#34;已经可见了。
我能做些什么让它有效?我完全错了吗? 我希望我以一种易于理解的方式解释了这个问题。如果我需要更好地解释我在做什么,我总是在这里,谢谢你的帮助。
答案 0 :(得分:1)
所以我有点解决了,我的想法是错误的。
你不应该像我一样尝试从“外部”找到正确的ViewHolder,而只是在一个绑定是正确的时候在OnBindViewHolder中“展开”它。
在moveTask中我做的就是我以前做的,但是我设置了要打开的卡的位置:
public void moveTask(int oldPosition, int position, Task task) {
if (oldPosition < position) {
myDataset.add(position, task);
myDataset.remove(oldPosition);
} else {
myDataset.remove(oldPosition);
myDataset.add(position, task);
}
mAdapter.notifyItemMoved(oldPosition, position);
//this is the important line, it set the variable
//openPos with the right number
mAdapter.setOpenPos(position);
mAdapter.notifyItemChanged(position);
mRecyclerView.scrollToPosition(position);
}
然后在适配器的onBindViewHolder中检查我是否在正确的位置:
@Override
public void onBindViewHolder(MyViewHolder holder, int pos) {
--set other fields--
// expand the right card
// if it's the first open it
if (pos == 0) {
holder.expand(holder.mHeader, holder.mExpanded);
// and collapse the opened one
if (openPos != -1 && openPos != pos) {
open.collapse(open.mHeader, open.mExpanded, true);
}
isFirst = holder;
open = holder;
openPos = 0;
}
// I'm in the position of the one I should open
// expand it
else if (openPos != -1 && pos == openPos) {
holder.expand(holder.mHeader, holder.mExpanded);
// and if I changed openPos with setOpenPos()
// collapse the "old" open card
if(openPos != open.getPosition()){
open.collapse(open.mHeader, open.mExpanded, true);
}
open = holder;
}
// if I'm in another card just collapse it
else {
holder.collapse(holder.mHeader, holder.mExpanded, true);
}
}
并且像这样工作正常。它甚至可以在不使用“setItemViewCacheSize”的情况下工作,但是如果没有它就会有其它奇怪的问题,所以现在我就把它留下来。
答案 1 :(得分:0)
首先,你不应该致电mRecyclerView.setItemViewCacheSize(myDataset.size())
。这意味着为列表中的每个项目创建一个ViewHolder,与使用LinearLayout没有太大区别。
其次,findViewHolderForPosition
仅检查儿童。这将被添加到文档中以供澄清。
在您的情况下,mAdapter.notifyItemMoved
不已足够,因为RV不知道必须重新绑定该项目。您还需要调用notifyItemChanged
,以便RV知道视图应该反弹。
创建两种视图类型(为简单起见,您不必)。一个崩溃,一个扩大。然后,当您想要移动和展开项目时,请致电:
public void moveTask(int oldPosition, int position, Task task) {
if (oldPosition < position) {
myDataset.add(position, task);
myDataset.remove(oldPosition);
} else {
myDataset.remove(oldPosition);
myDataset.add(position, task);
}
task.expanded = true;
mAdapter.notifyItemMoved(oldPosition, position);
mAdapter.notifyItemChanged(position);
}
//adapter
getItemViewType(int position) {
return myDataset.get(position).expanded ? TYPE_EXPANDED : TYPE_HEADER;
}
因为您已调用notifyItemChanged
RV将重新绑定该视图。