【问题标题】:RecyclerView marks unselected items as selectedRecyclerView 将未选中的项目标记为选中
【发布时间】:2020-07-10 08:47:49
【问题描述】:

我的 RecyclerView 在滚动时重复标记的项目。

我的 RecyclerView 有 10 行实际显示!如果我单击第一个,它的背景会突出显示。如果我现在向下滚动,则会突出显示另一个项目!

如果我向上滚动,第一个项目不再突出显示,而是另一个项目...

这是问题的图片:

任何我的 RecyclerViewAdapter:

public class SelectSongRecyclerViewAdapter extends RecyclerView.Adapter<SelectSongRecyclerViewAdapter.Holder> {
    private Song[] sSongs;
    private List<Song> selectedSongs;

    public SelectSongRecyclerViewAdapter(Song[] songs) {
        sSongs = songs;

        selectedSongs = new ArrayList<>();
    }

    @Override
    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_selectsongsview, parent, false);

        Holder holder = new Holder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(final Holder holder, final int position) {
        //holder.imvSong.setImageResource(R.drawable.standardartwork);
        holder.txvSongTitle.setText(sSongs[position].getTitle());
        holder.txvSongInfo.setText(sSongs[position].getArtists());

        holder.linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (selectedSongs.contains(sSongs[position])) {
                    selectedSongs.remove(sSongs[position]);
                    holder.linearLayout.setBackgroundResource(android.R.color.transparent);
                }
                else {
                    selectedSongs.add(sSongs[position]);
                    holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return sSongs != null ? sSongs.length : 0;
    }

    public Song[] getSelectedSongs() {
        Song[] songs = new Song[selectedSongs.size()];

        return selectedSongs.toArray(songs);
    }

    public class Holder extends RecyclerView.ViewHolder {
        LinearLayout linearLayout;
        ImageView imvSong;
        TextView txvSongTitle;
        TextView txvSongInfo;

        public Holder(View layout) {
            super(layout);

            linearLayout = (LinearLayout) layout;

            imvSong = (ImageView) layout.findViewById(R.id.imvSong);
            txvSongTitle = (TextView) layout.findViewById(R.id.adap_txvSongtitle);
            txvSongInfo = (TextView) layout.findViewById(R.id.adap_txvSongInfo);
        }
    }
}

我希望你能帮助我! 谢谢!

【问题讨论】:

  • 不要在“onBindViewHolder”中使用“位置”,而是尝试使用“holder.getAdapterPosition()”

标签: java android android-recyclerview


【解决方案1】:

这是我使用的工作代码!

调用onBindViewHolder时,只有在selectedSongs-List中的项目才会被选中!

@Override
public void onBindViewHolder(final Holder holder, int position) {
    holder.txvSongTitle.setText(sSongs[position].getTitle());
    holder.txvSongInfo.setText(sSongs[position].getArtists());

    if (!selectedSongs.contains(sSongs[position])) {
        holder.linearLayout.setBackgroundResource(android.R.color.transparent);
    }
    else {
        holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
    }

    holder.linearLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int pos = holder.getAdapterPosition();System.out.println(sSongs[pos].getTitle());

            if (selectedSongs.contains(sSongs[pos])) {
                selectedSongs.remove(sSongs[pos]);

                holder.linearLayout.setBackgroundResource(android.R.color.transparent);
            }
            else {
                selectedSongs.add(sSongs[pos]);

                holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
            }
        }
    });
}

【讨论】:

    【解决方案2】:

    这就是 RecyclerView 的工作原理: - 创建尽可能多的视图可以容纳在屏幕内,每次滚动时将视图传递给 onBindViewHolder,以便根据项目索引更新其数据

    现在,当单击其中一个视图时,您可以更改视图的背景颜色,当您滚动时,您会传递一个带有 backgroundColor (colorItemSelected) 的视图,然后只需更改它的数据。

    你应该做的是 onBindViewHolder 将视图的背景颜色设置为 colorItemSelected 如果项目被选中或透明。

    这里有一些合作

     public void onBindViewHolder(final Holder holder, final int position) {
        //holder.imvSong.setImageResource(R.drawable.standardartwork);
        holder.txvSongTitle.setText(sSongs[position].getTitle());
        holder.txvSongInfo.setText(sSongs[position].getArtists());
        if (selectedSongs.contains(sSongs[position])) {  
                  holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
        }else {
    holder.linearLayout.setBackgroundResource(android.R.color.transparent);
    }
    
        holder.linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (selectedSongs.contains(sSongs[position])) {
                    selectedSongs.remove(sSongs[position]);
                    holder.linearLayout.setBackgroundResource(android.R.color.transparent);
                }
                else {
                    selectedSongs.add(sSongs[position]);
                    holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
                }
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      试试这个适配器,

      public class SelectSongRecyclerViewAdapter extends RecyclerView.Adapter<SelectSongRecyclerViewAdapter.Holder> { 
      private Song[] sSongs;
      private List<Song> selectedSongs;
      
      public SelectSongRecyclerViewAdapter(Song[] songs) {
          sSongs = songs;
      
          selectedSongs = new ArrayList<>();
      } 
      
      @Override 
      public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
          View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_selectsongsview, parent, false);
      
          Holder holder = new Holder(view);
      
          return holder;
      } 
      
      @Override 
      public void onBindViewHolder(final Holder holder, final int position) {
          holder.bind(position); 
      
      } 
      
      @Override 
      public int getItemCount() { 
          return sSongs != null ? sSongs.length : 0;
      } 
      
      public Song[] getSelectedSongs() { 
          Song[] songs = new Song[selectedSongs.size()];
      
          return selectedSongs.toArray(songs);
      } 
      
      public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
          LinearLayout linearLayout;
          ImageView imvSong;
          TextView txvSongTitle;
          TextView txvSongInfo;
      
          public Holder(View layout) {
              super(layout);
      
              linearLayout = (LinearLayout) layout;
      
              imvSong = (ImageView) layout.findViewById(R.id.imvSong);
              txvSongTitle = (TextView) layout.findViewById(R.id.adap_txvSongtitle);
              txvSongInfo = (TextView) layout.findViewById(R.id.adap_txvSongInfo);
              linearLayout.setOnClickListener(this);
          }
      
          public void bind(int position){
              txvSongTitle.setText(sSongs[position].getTitle());
              txvSongInfo.setText(sSongs[position].getArtists());
      
              if (selectedSongs.contains(sSongs[getAdapterPosition()])) {
                  linearLayout.setBackgroundResource(android.R.color.transparent);
              }
              else {
                  linearLayout.setBackgroundResource(R.color.colorItemSelected);
              }
          }
      
          @Override
          public void onClick(View v) {
              if (selectedSongs.contains(sSongs[getAdapterPosition()])) {
                  selectedSongs.remove(sSongs[getAdapterPosition()]);
                  holder.linearLayout.setBackgroundResource(android.R.color.transparent);
              }
              else {
                  selectedSongs.add(sSongs[getAdapterPosition()]);
                  holder.linearLayout.setBackgroundResource(R.color.colorItemSelected);
              }
          }
      }
      

      }

      【讨论】:

        【解决方案4】:

        把你的onBindViewHolder改成这个

            @Override
                public void onBindViewHolder(final Holder holder, final int position) {
                    //holder.imvSong.setImageResource(R.drawable.standardartwork);
                    holder.txvSongTitle.setText(sSongs[position].getTitle());
                    holder.txvSongInfo.setText(sSongs[position].getArtists());
        
        holder.linearLayout.setBackgroundResource(selectedSongs.contains(sSongs[position]) ? R.color.colorItemSelected : android.R.color.transparent);
        
        
                    holder.linearLayout.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (selectedSongs.contains(sSongs[position])) {
                                selectedSongs.remove(sSongs[position]);
                                notifyDataSetChanged();
                            }
                            else {
                                selectedSongs.add(sSongs[position]);
                                notifyDataSetChanged();
                            }
                        }
                    });
                }
        

        【讨论】:

          【解决方案5】:

          Java

          private int position = -1;
          
          @Override
          public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            holder.itemView.setSelected(holder.getLayoutPosition() == this.position);
            holder.itemView.setOnClickListener(v -> {
               holder.itemView.setSelected(true);
               this.position = holder.getLayoutPosition();
            });
          }
          

          科特林

          val position = -1
          
          fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
              holder.itemView.isSelected = holder.layoutPosition == this.position
              holder.itemView.setOnClickListener { v: View? ->
                  holder.itemView.isSelected = true
                  this.position = holder.layoutPosition
              }
          }
          

          item_background.xml

          <?xml version="1.0" encoding="utf-8"?>
          <selector xmlns:android="http://schemas.android.com/apk/res/android">
              <item android:state_selected="true">
                  <shape>
                      <solid android:color="@android:color/holo_blue_bright" />
                  </shape>
              </item>
          
              <item>
                  <shape>
                      <solid android:color="@android:color/white" />
                  </shape>
              </item>
          </selector>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多