Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using multiple RecyclerView with one Adapter class

I have 3 RecyclerView to display most visited market, close by markets and favorite markets.

I have created 3 difference instance of MarketAdapter class for the three RecyclerView

Everything works fine, but my Activity implements one OnClickListener and I cant figure out which adapter was clicked. Is it possible to programmatically determine the Adapter that was clicked from the OnClickListener?

Here is my MarketAdapter Class

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

ArrayList<Markets> mMarket = new ArrayList<>();
Context mContext;
private final MarketsItemsClickListener mItemsClickListener;
private final MarketLongClickListener mLongClickListener;
private final MarketClickListener mClickListener;

public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener){
    mContext = context;
    mItemsClickListener = itemsClickListener;
    mLongClickListener = longClickListener;
    mClickListener = clickListener;
}

public interface MarketLongClickListener{
    void onLongClick(int position);
}

public interface MarketClickListener{
    void onClick(int position);
}

public interface MarketsItemsClickListener{
    void imageViewOnClickListener(View view, int position);
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    Context context = viewGroup.getContext();
    int layoutForListItem = R.layout.list_market;
    LayoutInflater inflater = LayoutInflater.from(context);
    boolean shouldAttachToParentImmediately = false;

    View view = inflater.inflate(layoutForListItem, viewGroup, shouldAttachToParentImmediately);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
    viewHolder.bindView(i);
}

@Override
public int getItemCount() {
    if(mMarket != null) return mMarket.size();
    return 0;
}

public void setData(ArrayList<Markets> markets){
    mMarket = markets;
    notifyDataSetChanged();
}

public void addData(Markets market, int position){
    mMarket.add(0, market);
    notifyDataSetChanged();
}

public Markets getItem(int position){return mMarket.get(position);}

class ViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener{

    ImageView mImageView;
    TextView mNameTextView, mCityTextView;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        mImageView = itemView.findViewById(R.id.image_view);
        mNameTextView = itemView.findViewById(R.id.name_text_view);
        mCityTextView = itemView.findViewById(R.id.city_text_view);

        itemView.setOnLongClickListener(this);
        itemView.setOnClickListener(this);
    }

    void bindView(int position){
        Markets market = getItem(position);

        mCityTextView.setText(market.getCity());
        mNameTextView.setText(market.getName());
    }

    @Override
    public void onClick(View v) {
        //Get position of Adapter
        int position = getAdapterPosition();
        //Handle the click
        mClickListener.onClick(position);
    }

    @Override
    public boolean onLongClick(View v) {
        return false;
    }
}

}

and OnClickListener from Activity

@Override
public void onClick(int position) {}
like image 775
Anga Avatar asked Nov 21 '18 16:11

Anga


People also ask

Can we use nested RecyclerView in Android?

A nested RecyclerView is an implementation of a RecyclerView within a RecyclerView. An example of such a layout can be seen in a variety of apps such as the Play store where the outer (parent) RecyclerView is of Vertical orientation whereas the inner (child) RecyclerViews are of horizontal orientations.

What is the purpose of the adapter class used with recycler view?

RecyclerView. Adapter base class for presenting List data in a RecyclerView , including computing diffs between Lists on a background thread. Adapters provide a binding from an app-specific data set to views that are displayed within a RecyclerView .


3 Answers

You can pass a tag in the constructor and get that tag back via a click listener to identify the click as

private final MarketsItemsClickListener mItemsClickListener;
private final MarketLongClickListener mLongClickListener;
private final MarketClickListener mClickListener;
private final String mTag;

public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener, String tag){
    mTag = tag
    mContext = context;
    mItemsClickListener = itemsClickListener;
    mLongClickListener = longClickListener;
    mClickListener = clickListener;
}

Modify the listener as

public interface MarketClickListener{
    void onClick(int position, String tag);
}

and the listener code in activity as

@Override
public void onClick(int position, String tag) {
    switch(tag){
        case "adapter1":
        break;
        case "adapter2":
        break;
        case "adapter3":
        break;
    }
}

and create adapter object as

 MarketAdapter adapter = new MarketAdapter("adapter1"....); 
 MarketAdapter adapter1 = new MarketAdapter("adapter2"....); 
 MarketAdapter adapter2 = new MarketAdapter("adapter3"....); 

and use

mClickListener.onClick(position, mTag);

Note: You can use enums as well

like image 66
Pavneet_Singh Avatar answered Nov 15 '22 12:11

Pavneet_Singh


You can add a attribute inside MarketAdapter so that you can tell what instance is that adapter.

Change your custom click listener to receive the adapter type:

public interface MarketClickListener {
    //You can change this to receive any data you want from the adapter
    void onClick(int position, int adapterType);
}

Add the constants, the identifier attribute and change the listener in your adatper:

public class MarketAdapter extends RecyclerView.Adapter<MarketAdapter.ViewHolder> {
    //The constants types
    public static int MOST_VISITED_MARKETS = 1;
    public static int CLOSE_BY_MARKETS = 2;
    public static int FAVORITE_MARKETS = 3;
    //New attribute
    private int adapterType;

    ...
    //Keep the listener
    private final MarketClickListener mClickListener;

        public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener, int adapterType){
            ...
            //Set the type
            adapterType = adapterType;
        }

        ...

}

In your activity:

mostVisitedRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.MOST_VISITED_MARKETS ));
closeByRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.CLOSE_BY_MARKETS));
favoritesRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.FAVORITE_MARKETS));

In your view holder, change the onClick:

@Override
    public void onClick(View v) {
        //Get position of Adapter
        int position = getAdapterPosition();
        //Handle the click
        mClickListener.onClick(position,adapterType);
    }

I didn't test this but I think it will do the trick. Try it out.

like image 25
Giovanne Avatar answered Nov 15 '22 14:11

Giovanne


If you want to do it this way, I would add a new variable to the adapters constructor, and then use a case/if statement to determine what you want to do in your onbindviewholder.

like image 41
Joshua Best Avatar answered Nov 15 '22 13:11

Joshua Best