【问题标题】:wrong item changes in recyclerviewrecyclerview中的错误项目更改
【发布时间】:2017-07-11 08:48:56
【问题描述】:

大家好,我陷入困境并需要帮助:

每个项目都有一个CheckBox,我在RecyclerView 中为我的项目的根元素设置setOnLongClickListener,如下所示:

    holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
        public boolean onLongClick(View arg0) {


            if (chk_visible)
            {
                return  true ;
            }
            holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
            chk_visible = true ;
            checkedItemsCNT = 1 ;
            deleteListVideoCourses.add(data.get(holder.getAdapterPosition())) ;
            notifyDataSetChanged() ;
            return  true ;
        }
    });

如果我向下滚动,当我长按其中一个项目时,会检查错误项目的CheckBox

【问题讨论】:

  • 请发布您的完整适配器代码或getView方法代码
  • @배준모 代码太多...
  • 查看@Doomsknight 的回答。这和我的想法一样

标签: android android-recyclerview


【解决方案1】:

这是因为当您使用 RecycleView 时,它会在您每次滚动时重用您的视图。 RecycleView 像这样重用你的资源

因此,当您滚动时,它会显示错误的视图状态

解决方案

如果您为签入onBindViewHolder 编写任何逻辑,那么您必须同时使用这两个部分来判断真假

if(yourCondition){
   //code if condition is true
}else {
   //code if condition is false
}

其他解决方案

您只需使用一条语句来阻止您的RecycleView 以像这样重用您的视图状态即可解决它

@Override
public void onBindViewHolder(ReqNotificationAdapter.MyViewHolder holder, int position) {

    holder.setIsRecyclable(false);
    //.................your other code
}

我用它来解决我的问题.. 希望它能解决你的问题,如果你没有问题,请停止按你的目的回收。

【讨论】:

  • 我这样做了,但是这样没有 CheckBox 被选中!
  • holder.setIsRecyclable(false);
  • 第一个:我应该检查什么以确保我检查正确的复选框?
  • 如果你这样做,它认为你需要编辑你的条件....让我检查一下
  • “chk_visible”的目的是什么。是否只想勾选复选框?
【解决方案2】:

可能是您的绑定问题,而不是值的设置问题。

一个常见的错误是没有取消检查绑定中的视图。

确保您在哪里设置为选中,您有一个 else 语句并将其设置为未选中。

RecyclerView 和 Listview 在滚动时重用视图,其中包括任何以前选中的框。因此,在适当的情况下取消选中它们很重要。

public void bindView(View view,   ..... //varies on implementation. rough idea.
{
  CheckBox mycheckbox = (CheckBox)view.findViewById(R.id.myidofcheckbox);


  int pos = view.getPosition();

  if(pos == 1) //example
     mycheckbox.setChecked(true);
  else
     mycheckbox.setChecked(false);

【讨论】:

  • 所以如果条件是位置,我现在应该如何检查当前位置复选框?
  • @user3422607 你应该有一个方法bindView(View view, ..,你可以在其中调用int pos = view.getPosition(); 然后检查pos并采取相应的行动。
  • 这正是问题所在,首先:positin 是正确的!第二:我应该如何检查正确的项目复选框(正确的位置)?
  • 我的意思是如何访问位置 x 的 CheckBox ?!
  • @user3422607 在绑定中设置setOnLongClickListener,暂时不要使用holder。使用方法自带的view
【解决方案3】:

是的,ListView 和 RecyclerView 会发生这种情况

试试这个代码,

 holder.faviorateVideoItemRelative.setTag(position);
 holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
    public boolean onLongClick(View arg0) {

        int tempPos = (int)holder.faviorateVideoItemRelative.getTag();

        if (chk_visible)
        {
            return  true ;
        }

         if(!holder.chk_faviorateVideo.isChecked())
         {
             holder.chk_faviorateVideo.setChecked(true);
         }
         else
         {
             holder.chk_faviorateVideo.setChecked(false);
         }

    holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
        chk_visible = true ;
        checkedItemsCNT = 1 ;
        deleteListVideoCourses.add(data.get(tempPos)) ;
        notifyDataSetChanged() ;
        return  true ;
    }
});

希望对你有所帮助。

【讨论】:

【解决方案4】:

当您初始化 OnLongClickListener 时,它会在视图不再可见时被重用,因为它们已被缓存。 为了解决这个问题,创建一个新类来显式地将对象链接到侦听器,而不仅仅是视图。 例如:

private class BufferVideoLongClickListener implements View.OnLongClickListener {

    private VideoObject video; // And other stuff like checked, etc

    BufferVideoLongClickListener(VideoObject video, ...) {
        this.video = video;
        ...
    }

    @Override
    public void onLongClick(View view) {
        // Do your check and other things
        if(checked)
          ...
    }
}

在你的 onBindViewHolder 中:

holder.faviorateVideoItemRelative.setOnLongClickListener(new BufferVideoLongClickListener(video, ...));

【讨论】:

  • 我应该通过复选框并且持有人在错误的位置给我复选框
  • 您必须仅使用支架来存储项目的视图。支票必须在您要显示的对象中。并且正如 Doomsknight 所说,只使用 bind 方法的 view 参数。
【解决方案5】:

解决方案 1:

你可以重写两个方法getItemId,getItemViewType。

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

像这样:

public class EasyAdapter  extends RecyclerView.Adapter<EasyAdapter.ViewHolder>{


    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }
}

解决方案 2: 将 setIsRecyclable 设置为 false。

EasyAdapter easyAdapter=new EasyAdapter();
easyAdapter.setIsRecyclable(false);

【讨论】:

    【解决方案6】:

    使用上述解决方案后,

    以下解决方案对我来说很有吸引力。

     @Override
    public long getItemId(int position) {
        return position;
    }
    
    @Override
    public int getItemViewType(int position) {
        return position;
    }
    

    使用holder.setIsRecyclable(false) 也会在您在整个滚动过程后返回所需的选择时删除它。

    【讨论】:

      猜你喜欢
      • 2018-07-30
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多