Ajay Gohel
Ajay Gohel

Reputation: 243

How to implement OnClickListener in RecyclerView?

I want to make selction menu for profiles using RecyclerView. I created it with RecyclerView. Now i am getting problem in onItemClickListener. I want to change background of CardView and Text Color on item select. at a time only one item can be selected. And on next button click it should redirect to activity according to selection.

This is my screen looks like:

Screen

public class SelectProfile extends AppCompatActivity {

private String[] mTextData;
private int[] mImgData;
RecyclerView recyclerView;
private ProfileAdapter profileAdapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_select_profile);

    recyclerView = findViewById(R.id.recycleProfile);
    RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,2);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setHasFixedSize(true);

    profileAdapter = new ProfileAdapter();
    recyclerView.setAdapter(profileAdapter);

    int imgData[] = {R.drawable.ic_college_icon,R.drawable.ic_parent,R.drawable.ic_student,R.drawable.ic_teaching,
                    R.drawable.ic_non_teaching,R.drawable.ic_other};
    final String textData[] = {"School/College","Parent","Student","Teaching Staff","Non-Teaching Staff","Other"};

    profileAdapter.setData(imgData,textData);

}

private class ProfileAdapter extends RecyclerView.Adapter<ProfileAdapter.ProfileAdapterViewHolder>{

    int index = -1;

    @NonNull
    @Override
    public ProfileAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        int layoutIdForListItem = R.layout.profile_item;
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        boolean shouldAttachToParent = false;

        View view = layoutInflater.inflate(layoutIdForListItem,parent,shouldAttachToParent);
        return new ProfileAdapterViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ProfileAdapterViewHolder holder,final int position) {
        int mImage = mImgData[position];
        String mText = mTextData[position];

        holder.img.setImageResource(mImage);
        holder.txt.setText(mText);

         holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                index = position;
                notifyDataSetChanged();
            }
        });

        if (index == position){
            holder.card.setBackground(getResources().getDrawable(R.drawable.bg_select_profile));
                holder.txt.setTextColor(getResources().getColor(R.color.colorPrimary));
        }else {
            holder.card.setCardBackgroundColor(getResources().getColor(android.R.color.white));
            holder.txt.setTextColor(getResources().getColor(R.color.gray));
        }
    }


    @Override
    public int getItemCount() {
        if (null == mImgData) return 0;
        return mImgData.length;
    }

    public class ProfileAdapterViewHolder extends RecyclerView.ViewHolder  {
        private final AppCompatImageView img;
        private final TextView txt;
        private final CardView card;
        private ProfileAdapterViewHolder(@NonNull View itemView) {
            super(itemView);
            img = itemView.findViewById(R.id.img);
            txt = itemView.findViewById(R.id.txt);
            card = itemView.findViewById(R.id.card);
        }



    }

    private void setData(int[] imgData,String[] txtData){
        mImgData = imgData;
        mTextData = txtData;
        notifyDataSetChanged();
    }

}
}

Upvotes: 1

Views: 3329

Answers (5)

Tanveer Munir
Tanveer Munir

Reputation: 1968

You can pass a listener object in the constructor which implements by fragment OR activity

/**
 * item click interface of adapter
 */
public interface ProfileAdapterListener {
    void onItemClick(int position, ProfileAdapterViewHolder holder)
} 

This interface implements by Fragment OR Activity

/**
 * On item clicked Implement Method from adapter listener.
 *
 * @param position
 */
@Override
public void onItemClick(int position, ProfileAdapterViewHolder holder) {
    // Here you can call that method 
}

Then you pass this listener in the constructor of the adapter.

private void buildRecyclerView() {
  profileAdapter = new ProfileAdapter(this);
  recyclerView.setAdapter(profileAdapter);
}

In the constructor, you can assign like this

private ProfileAdapterListener mProfileAdapterListener;
 public OfferAdapter(ProfileAdapterListener mProfileAdapterListener) {
        this.mProfileAdapterListener = mProfileAdapterListener
        }
    }

Now you can use this listener by setting click listener on any Viwe like this

holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mProfileAdapterListener.onItemClick(position, holder);
            }
        });

It returns to call the method of onItemClick which implements this method. This is the safe and sound method to click on each item or any view in the item.

Upvotes: 0

Hasanuzzaman Mamun
Hasanuzzaman Mamun

Reputation: 166

Your approach of using an Index variable is right, add getter and setter method for the index. But you can't set the onClickListener on the adapter. Instead, set the listener on the card view like this ->

holder.card.setOnItemClickListener(new ClickListener() {
            @Override
            public void onItemClick(int position, View v) {
                index = position;
                notifyDataSetChanged();
            }
        });

Add this method inside your adapter class ->

public int getSelectedIndex(){
    return this.index; }

After that, from your Activity, inside your NEXT button's onClickListener do the following thing,

    btnNext.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(profileAdapter.getSelectedIndex() == 1)
//goto activity of your desire and so on
                    }
                });

Upvotes: 1

Longalei
Longalei

Reputation: 492

change and adjust your adapter like as below:

private class ProfileAdapter extends RecyclerView.Adapter<ProfileAdapter.ProfileAdapterViewHolder>{

int index = -1;

@NonNull
@Override
public ProfileAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    Context context = parent.getContext();
    int layoutIdForListItem = R.layout.profile_item;
    LayoutInflater layoutInflater = LayoutInflater.from(context);
    boolean shouldAttachToParent = false;

    View view = layoutInflater.inflate(layoutIdForListItem,parent,shouldAttachToParent);
    return new ProfileAdapterViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ProfileAdapterViewHolder holder, int position) {
    int mImage = mImgData[position];
    String mText = mTextData[position];

    holder.img.setImageResource(mImage);
    holder.txt.setText(mText);

    if (index == position){
        holder.card.setCardBackgroundColor(getResources().getColor(R.color.colorPrimary));
        holder.txt.setTextColor(getResources().getColor(R.color.colorPrimary));
    }else {
        holder.card.setCardBackgroundColor(getResources().getColor(android.R.color.white));
        holder.txt.setTextColor(getResources().getColor(R.color.gray));
    }
}


@Override
public int getItemCount() {
    if (null == mImgData) return 0;
    return mImgData.length;
}

public class ProfileAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private final AppCompatImageView img;
    private final TextView txt;
    private final CardView card;
    private ProfileAdapterViewHolder(@NonNull View itemView) {
        super(itemView);
        img = itemView.findViewById(R.id.img);
        txt = itemView.findViewById(R.id.txt);
        card = itemView.findViewById(R.id.card);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        setIndex(getAdapterPosition());

       notifyDataSetChanged();
    }
}

private void setData(int[] imgData,String[] txtData){
    mImgData = imgData;
    mTextData = txtData;
    notifyDataSetChanged();
}

public void setOnItemClickListener(ClickListener clickListener){
    mClickListener = clickListener;
}


private void setIndex(int index){
  this.index=index;
}

}

you may not need the ClickListener.

Upvotes: 0

Mayank Sharma
Mayank Sharma

Reputation: 2835

Add OnClickListner on holder root view , best place to write listener is in onCreateViewHolder , so replace your onCreateViewHolder with following

public ProfileAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            Context context = parent.getContext();
            int layoutIdForListItem = R.layout.profile_item;
            LayoutInflater layoutInflater = LayoutInflater.from(context);
            boolean shouldAttachToParent = false;

            View view = layoutInflater.inflate(layoutIdForListItem,parent,shouldAttachToParent);
     ViewHolder viewHolder = new ViewHolder(view);
 view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                postion=viewHolder.getAdapterPosition();
                notifyDataSetChanged();
            }
        });

            return viewHolder ;
        }

Upvotes: 0

Abhilash Harsole
Abhilash Harsole

Reputation: 254

Use your card view as a parent layout for your recycler view item and apply on click listener to that card view in recycler view adapter.

holder.your_card_view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

    // get you recyclerview item position here
}

});

Upvotes: 0

Related Questions