简体   繁体   English

Recyclerview意外onclick项目

[英]Recyclerview unexpectedly onclick items

I am programming a simple game in android and I encountered a problem with recyclerview . 我在android中编写一个简单的游戏,遇到recyclerview问题。 I need help please , tnx :) 我需要帮助,tnx :)

I have an activity that create an arrayList and add my data to it then pass it to my recyclerview 's adapter . 我有一个活动,该活动创建一个arrayList并将其添加到数据中,然后将其传递到recyclerview的适配器。 In the adapter I write code that user can't select more than an image. adapter我编写了用户只能选择一张图片的代码。 Now the problem is there when I select first item and then scroll recyclerview I see that one of the last three items is selected. 现在,当我选择第一个项目然后滚动recyclerview时,问题就出现了,我看到选择了最后三个项目之一。 And this case happen for only fist line items and last three items too. 这种情况仅发生在第一项订单项和最后三项订单中。

What can I do for that ? 我该怎么办?

My activity : 我的活动:

public class page_register extends AppCompatActivity {

    Activity _A;
    Context _C;

    private RecyclerView recyclerView1, recyclerView2;
    private AdsAdapter adapter1;
    private Avatar2Adapter adapter2;

    private ArrayList<Ads> adsArrayList;

    TextView Tv1, Tv2;
    EditText ET1, ET2;
    Button BT_First, BT_Second;
    ImageButton BT_Back;
    ImageView img_first, img_second;
    CardView cardView1, cardView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.page_register);
        M_UI.SetOffKeyboard(this);
        M_Font.Initial(this);

        _A = this;
        _C = this;

        Initial();


        adsArrayList = new ArrayList<>();
        adsArrayList.add(new Ads(R.drawable.a1));
        adsArrayList.add(new Ads(R.drawable.a2));
        adsArrayList.add(new Ads(R.drawable.a3));
        adsArrayList.add(new Ads(R.drawable.a4));
        adsArrayList.add(new Ads(R.drawable.a5));
        adsArrayList.add(new Ads(R.drawable.a6));
        adsArrayList.add(new Ads(R.drawable.a7));
        adsArrayList.add(new Ads(R.drawable.a8));
        adsArrayList.add(new Ads(R.drawable.a9));
        adsArrayList.add(new Ads(R.drawable.a10));
        adsArrayList.add(new Ads(R.drawable.a11));
        adsArrayList.add(new Ads(R.drawable.a12));
        adsArrayList.add(new Ads(R.drawable.a13));
        adsArrayList.add(new Ads(R.drawable.a14));
        adsArrayList.add(new Ads(R.drawable.a15));
        adsArrayList.add(new Ads(R.drawable.a16));             
        adsArrayList.add(new Ads(R.drawable.a17));
        adsArrayList.add(new Ads(R.drawable.a18));
        adsArrayList.add(new Ads(R.drawable.a19));
        adsArrayList.add(new Ads(R.drawable.a20));
        adsArrayList.add(new Ads(R.drawable.a21));
        //--------------------------------------------

        adapter1 = new AdsAdapter(adsArrayList, this, _C, _A, recyclerView1, 0);
        adapter2 = new Avatar2Adapter(adsArrayList, this, _C, _A, recyclerView2, 0);

        RecyclerView.LayoutManager layoutManager1 = new GridLayoutManager(_C, 3);
        RecyclerView.LayoutManager layoutManager2 = new GridLayoutManager(_C, 3);
        recyclerView1.setLayoutManager(layoutManager1);
        recyclerView2.setLayoutManager(layoutManager2);

        recyclerView1.setAdapter(adapter1);
        recyclerView2.setAdapter(adapter2);
    }     

    public void Initial() {
        recyclerView1 = (RecyclerView) findViewById(R.id.recycler_view1);
        recyclerView2 = (RecyclerView) findViewById(R.id.recycler_view2);    

    }
}

and my adapter : 和我的适配器:

public class AdsAdapter extends RecyclerView.Adapter<AdsAdapter.AdsViewHolder> {

    private ArrayList<Ads> dataList;

    Context _C1;
    Activity _A1;

    RecyclerView r;

    int SelectedPos = 0;

    int id_prev;
    CardView CV_Prev = null;

    public AdsAdapter(ArrayList<Ads> dataList, FragmentActivity activity, Context _C, Activity _A, RecyclerView recyclerView, int i) {
        this.dataList = dataList;

        _A1 = _A;
        _C1 = _C;
        r = recyclerView;

    }


    @Override
    public AdsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        final View view = layoutInflater.inflate(R.layout.avatars, parent, false);


        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View SelectCardView) {

                try {

                    if (CV_Prev != null) {
                        CV_Prev.findViewById(R.id.img_select).setVisibility(View.INVISIBLE);
                    }
                    SelectCardView.findViewById(R.id.img_select).setVisibility(View.VISIBLE);



                    CV_Prev = (CardView) SelectCardView;

                } catch (Exception e) {
                    Toast.makeText(_C1, e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });

        return new AdsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(AdsViewHolder holder, int position) {

         holder.CV_item.setTag(position);
        //------------------------------------------------------------------
        holder.img_avatar.setImageResource(dataList.get(position).getImage());


    }


    @Override
    public int getItemCount() {
        return dataList.size();
    }


    class AdsViewHolder extends RecyclerView.ViewHolder {

        ImageView img_avatar;
        CardView CV_item;

        AdsViewHolder(View itemView) {
            super(itemView);
            //-----------------------------------------------------------
            img_avatar = (ImageView) itemView.findViewById(R.id.img_avatar);
            CV_item = (CardView) itemView.findViewById(R.id.cardView);

        }

    }
}

my view : 我的观点 :

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/cardView"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="#00ffffff"
    android:layoutDirection="ltr"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    card_view:cardBackgroundColor="#B2EBF2"
    card_view:cardCornerRadius="5dp"
    card_view:cardElevation="5dp"
    card_view:cardUseCompatPadding="true">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">


        <ImageView
            android:id="@+id/img_avatar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00ffffff"
            card_view:srcCompat="@drawable/a1" />

        <ImageView
            android:id="@+id/img_select"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:visibility="invisible"
            card_view:srcCompat="@mipmap/ic_check_circle_black_48dp" />


    </RelativeLayout>


</android.support.v7.widget.CardView>

my model : 我的模特:

public class Ads {

    private int image;



    public Ads(int image) 

      {
        this.image = image;
      }



    public void setImage(int image) {this.image = image;}

    public int getImage() {return image;}

  }

below image shows my mean : 下图显示了我的意思:

在此处输入图片说明

*** I tried to set id for each card and image and selecting them by their id but that didn't help too. ***我尝试为每个卡和图像设置ID,并通过其ID选择它们,但这也无济于事。

This happens because recycler view recycles the view in OnBindViewHolder.To solve this. 发生这种情况是因为回收站视图回收了OnBindViewHolder中的视图。

create a global variable to store the clicked position. 创建一个全局变量来存储单击位置。

private mItemSelected=-1;

Then inside viewholder add the clickListener and onClick store the position of the clicked item. 然后在viewholder内部添加clickListener和onClick存储被单击项的位置。

class AdsViewHolder extends RecyclerView.ViewHolder {

    ImageView img_avatar;
    CardView CV_item;
    AdsViewHolder(View itemView) {
        super(itemView);
        //-----------------------------------------------------------
        img_avatar = (ImageView) itemView.findViewById(R.id.img_avatar);
        CV_item = (CardView) itemView.findViewById(R.id.cardView);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mItemSelected=getAdapterPosition();
                notifyDataSetChanged();
            }
        });

    }

}

And in inside OnBindViewHolder, 在OnBindViewHolder内部,

if(mItemSelected==position){

//code for image selected.
  holder.CV_item.setVisibility(View.VISIBLE);

}else{

//code for image unselected.
  holder.CV_item.setVisibility(View.INVISIBLE);

}   

Also remove the click listener that has been added in the createViewholder instead add it inside the constructor of AdsViewHolder as added above. 还要删除已添加到createViewholder中的单击侦听器,而是将其添加到上面添加的AdsViewHolder的构造函数中。

EDIT :Check this updated code.Hope it helps you. 编辑 :检查此更新的代码。希望它对您有帮助。

public class AdsAdapter extends RecyclerView.Adapter<AdsAdapter.AdsViewHolder> {

private ArrayList<Ads> dataList;
Context _C1;
Activity _A1;
RecyclerView r;
int SelectedPos = 0;
int id_prev;
CardView CV_Prev = null;
private int mItemSelected=-1;

public AdsAdapter(ArrayList<Ads> dataList, FragmentActivity activity, Context _C, Activity _A, RecyclerView recyclerView, int i) {
    this.dataList = dataList;
    _A1 = _A;
    _C1 = _C;
    r = recyclerView;

}


@Override
public AdsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    final View view = layoutInflater.inflate(R.layout.avatars, parent, false);
    return new AdsViewHolder(view);
}

@Override
public void onBindViewHolder(AdsViewHolder holder, int position) {

 holder.CV_item.setTag(position);
holder.img_avatar.setImageResource(dataList.get(position).getImage());
    if(mItemSelected==position){

     //code for image selected. 
        holder.CV_item.setVisibility(View.VISIBLE);

    }else{

    //code for image unselected. 
        holder.CV_item.setVisibility(View.INVISIBLE);

    }

}

@Override
public int getItemCount() {
    return dataList.size();
}


class AdsViewHolder extends RecyclerView.ViewHolder {

    ImageView img_avatar;
    CardView CV_item;
    AdsViewHolder(View itemView) {
        super(itemView);
        //-----------------------------------------------------------
        img_avatar = (ImageView) itemView.findViewById(R.id.img_avatar);
        CV_item = (CardView) itemView.findViewById(R.id.cardView);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mItemSelected=getAdapterPosition();
                notifyDataSetChanged();
            }
        });

    }

  }
}

Replace this code 替换此代码

 if (CV_Prev != null && CV_Prev.findViewById(R.id.img_select).getVisibility() == View.VISIBLE) { CV_Prev.findViewById(R.id.img_select).setVisibility(View.INVISIBLE); } if(SelectCardView.findViewById(R.id.img_select).getVisibility() == View.INVISIBLE) SelectCardView.findViewById(R.id.img_select).setVisibility(View.VISIBLE); 

or you can create a global variable to store the clicked position and change its Visibility after second click 或者您可以创建一个全局变量来存储单击的位置并在第二次单击后更改其可见性

See if this helps: https://stackoverflow.com/a/46641850/4469112 I just explained how to properly set the on click listeners to recycler view's adapter and view holders. 看看是否有帮助: https : //stackoverflow.com/a/46641850/4469112我刚刚解释了如何正确地将on click侦听器设置为recycler view的适配器和视图持有者。 The important part is to set the listener to the view holder (and no directly to the view), and then to let the view holder to set itself as listener to the passed view. 重要的部分是将侦听器设置为视图持有者(而不是直接设置为视图),然后让视图持有者将自身设置为传递的视图的侦听器。 Remember the view is recycled and the content is binded to it at runtime (when you scroll in your case), that's why you're seeing the selection 'transferred' to the other items. 请记住,视图是回收的,并且内容在运行时绑定(在您的情况下滚动时)绑定到该视图,这就是为什么您看到选择“已转移”到其他项的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM