Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView onClick for multiple buttons and handling from Activity

I'm using RecyclerView with CardView and inside the CardView have 2 buttons. Now, have implemented the onClick events by implementing View.OnClickListener by the ViewHolder static class and overriding the event (its working )like

    @Override
    public void onClick(View v) {

        if (v.getId() == mClassBtn.getId()){

        }
        else if (v.getId() == mDaysBtn.getId()){

        }
     }

Looking for a solution/pattern to handle the Click in the Activity class like

adapter = new ItemsListAdapter(getActivity(), data, new CustomItemClickListener() { 

    @override
    public void onItemClick(View v, int position) {

       Log.d(TAG, "clicked position:" + position);
       // which button clicked and separate action for each button
    } 
});
// CustomItemClickListener -- interface in the adapter class which holds the click event .

The above code working fine and able to log the Clicks but not able to differentiate which button has clicked.

Appreciate any help

like image 543
user2695433 Avatar asked May 29 '17 08:05

user2695433


People also ask

How add onClick to RecyclerView?

Update the ViewHolder to take in onClick() as a parameter. In the initializer, call setOnClickListener{} on the itemView . That's it! Your RecyclerView is now responsive so time to get your click on!

What is the difference between onCreateViewHolder and onBindViewHolder?

This method internally calls onBindViewHolder to update the ViewHolder contents with the item at the given position and also sets up some private fields to be used by RecyclerView. This method calls onCreateViewHolder to create a new ViewHolder and initializes some private fields to be used by RecyclerView.

How many times is called onCreateViewHolder?

By default it have 5. you can increase as per your need. Save this answer.

What does notifyDataSetChanged do in RecyclerView?

What does notifyDataSetChanged() do on recyclerview ? Notify any registered observers that the data set has changed. There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred.


2 Answers

here is the best way to achieve that:--

this is how i have implemented

public class FollowersDetailsAdapter extends RecyclerView.Adapter<FollowersDetailsAdapter.MyViewHolder> {

    private List<GetUserFollowDetailsResponseData> followersList;
    Context context;
    public FollowersDetailsAdapterListener onClickListener;


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView rv_tv_follower_name, rv_tv_follower_desig;
        public CircleImageView rv_iv_follower_image;
        RelativeLayout rv_rel_layout_followers, rel_layout_followers;
        LikeButton rv_iv_follower_icon;

        public MyViewHolder(View view) {
            super(view);
            rv_rel_layout_followers = (RelativeLayout) view.findViewById(R.id.rv_rel_layout_followers);
            rel_layout_followers = (RelativeLayout) view.findViewById(R.id.rel_layout_followers);
            rv_iv_follower_image = (CircleImageView) view.findViewById(R.id.rv_iv_follower_image);
            rv_tv_follower_name = (TextView) view.findViewById(R.id.rv_tv_follower_name);
            rv_tv_follower_desig = (TextView) view.findViewById(R.id.rv_tv_follower_desig);
            rv_iv_follower_icon = (LikeButton) view.findViewById(R.id.rv_iv_follower_icon);
            rel_layout_followers.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onClickListener.iconTextViewOnClick(v, getAdapterPosition());
                }
            });
        }

    }

    public FollowersDetailsAdapter(List<GetUserFollowDetailsResponseData> FollowersList, FollowersDetailsAdapterListener listener) {
        this.followersList = FollowersList;
        this.onClickListener = listener;

    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.followers_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        if (followersList.get(position).getImage() != null && !followersList.get(position).getImage().trim().equalsIgnoreCase("")) {
            Picasso.with(context)

                    .load(followersList.get(position).getImage())
                    .resize(200, 200).into(holder.rv_iv_follower_image);
        }

        holder.rv_tv_follower_name.setText(followersList.get(position).getName());
        holder.rv_tv_follower_desig.setText(followersList.get(position).getDescription());
        if (followersList.get(holder.getAdapterPosition()).getID() == Integer.parseInt(ApplicationPreference.getUserId())) {
            holder.rv_iv_follower_icon.setVisibility(View.GONE);
        } else {
            holder.rv_iv_follower_icon.setVisibility(View.VISIBLE);
            if (followersList.get(position).getIsFollowing() == 0) {
                holder.rv_iv_follower_icon.setLiked(false);
            } else if (followersList.get(position).getIsFollowing() == 1) {
                holder.rv_iv_follower_icon.setLiked(true);
            }


        }
        holder.rv_iv_follower_icon.setOnLikeListener(new OnLikeListener() {
            @Override
            public void liked(LikeButton likeButton) {

                onClickListener.iconImageViewOnClick(likeButton, position);
            }

            @Override
            public void unLiked(LikeButton likeButton) {
                onClickListener.iconImageUnFollowOnClick(likeButton, position);
            }
        });

    }

    public interface FollowersDetailsAdapterListener {

        void iconTextViewOnClick(View v, int position);

        void iconImageViewOnClick(View v, int position);

        void iconImageUnFollowOnClick(View v, int position);
    }

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

and in your activity where you initialize the adapter--

 followersDetailsAdapter = new FollowersDetailsAdapter(followersList, new FollowersDetailsAdapter.FollowersDetailsAdapterListener() {
            @Override
            public void iconTextViewOnClick(View v, int position) {
                gotoUserProfile(followersList.get(position).getID());

            }

            @Override
            public void iconImageViewOnClick(View v, int position) {

                followUserProfile(followersList.get(position).getID(),1);
            }

            @Override
            public void iconImageUnFollowOnClick(View v, int position){

                followUserProfile(followersList.get(position).getID(),0);
            }
        }); 
like image 183
headshoT Avatar answered Oct 05 '22 09:10

headshoT


Please, try this principle to create a communication between activity, adapter through the interface, I hope this principle helps you:

Model Class:

public class YourModel {

    private String firstName;
    private String lastName;

    public YourModel(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    //... setters & getters
}

Interface:

public interface AdapterCallback {
    void onClickCallback(YourModel itemModel);
}

Adapter:

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

    private List<YourModel> data;
    private AdapterCallback callback;
    private Context context;

    public YourAdapter(List<YourModel> data, AdapterCallback callback) {
        this.data = data;
        this.callback = callback
    }

    @Override
    public YourAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View item = inflater.inflate(R.layout.item_recycler, parent, false);
        return new ViewHolder(item);
    }

    @Override
    public void onBindViewHolder(YourAdapter.ViewHolder holder, int position) {
        YourModel itemModel = data.get(position);

        String lastName  = itemModel.getLastName();  
        String firstName = itemModel.getFirstName();

        holder.tvFirstName.setText(firstName);
        holder.tvLastName.setText(lastName);

        holder.tvFirstName.setOnClickListener { 
           callback.onClickCallback(itemModel));
        }
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {

        private TextView tvFirstName;
        private TextView tvLastName;

        ViewHolder(View itemView) {
            super(itemView);
            tvFirstName = (TextView) itemView.findViewById(R.id.tv_first);
            tvLastName  = (TextView) itemView.findViewById(R.id.tv_last);
        }

}

Activity:

public class MyActivity extends AppCompatActivity implements AdapterCallback {

private YourAdapter adapter;
private List<YourModel> items;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 1. init your list && fill it with needed data
    // 2. init your adapter 
    // 3. put your list as parameter into constructor + interface
    items = new ArrayList<YourModel>()
    items.add(YourModel("John", "Doe"));
    items.add(YourModel("Bob", "Marley"));
    adapter = new YourAdapter(items, this)
}

@Override
public void onClickCallback(YourModel itemModel) {
    Toast.makeText(this, itemModel.getFirstName(), Toast.LENGTH_SHORT).show();
}

I think that this information is enough to understand what I mean. The same principle you can create multiple OnClick methods in your interface or put one onClick for a few buttons and check id or something else to get needed information that you need. Good luck

like image 38
Alexander Khyzhun Avatar answered Oct 05 '22 09:10

Alexander Khyzhun