androidandroid-recyclerviewonclicklistenernestedrecyclerview

Nested RecyclerView OnclickListener


I have nested RecyclerView (MainRecyclerview and ChildRecyclerview) with two Adapters(MainRecyclerviewAdapter and ChildRecyclerviewAdapter), i create an interface to handle click for childRecyclerview, but i can only access that click in MainRecyclerviewAdapter. I want to know how to handle click for items in childRecyclerview in MainActivity, thanks.

Here is my code:

//MainActivity

public class MainActivity extends AppCompatActivity {

List<Section> sectionList = new ArrayList<>();
RecyclerView mainRecyclerView;
LinearLayoutManager layoutManager;
MainRecyclerAdapter mainRecyclerAdapter;

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

    initData();
    initRecyclerView();



}

}

//ChildRecyclerAdapter

public class ChildRecyclerAdapter extends RecyclerView.Adapter<ChildRecyclerAdapter.ChildViewHolder> {

private final List<String> items;
private OnItemClickListener mListener;

public ChildRecyclerAdapter(List<String> items) {
    this.items = items;
}

public void setOnItemClickListener(OnItemClickListener listener) {
    mListener = listener;
}

@NonNull
@Override
public ChildViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
    return new ChildViewHolder(view, mListener);
}

@Override
public void onBindViewHolder(@NonNull ChildViewHolder holder, int position) {
    holder.itemTextView.setText(items.get(position));
}

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


public class ChildViewHolder extends RecyclerView.ViewHolder {

    TextView itemTextView;

    ChildViewHolder(final View itemView, OnItemClickListener listener) {
        super(itemView);
        itemTextView = itemView.findViewById(R.id.txt_item_view);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null) {
                    int position = getBindingAdapterPosition();
                    if (position != RecyclerView.NO_POSITION) {
                        String item = items.get(position);
                        listener.onItemClick(item);
                    }
                }
            }
        });
    }
}

}

//MainRecyclerAdapter

public class MainRecyclerAdapter extends RecyclerView.Adapter<MainRecyclerAdapter.MainViewHolder> {

List<Section> sectionList;

public MainRecyclerAdapter(List<Section> sectionList) {
    this.sectionList = sectionList;
}

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

    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.section_row, parent, false);
    return new MainViewHolder(view);
}

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

    Section section = sectionList.get(position);
    String sectionName = section.getSectionName();
    List<String> items = section.getSectionItems();

    holder.sectionNameTextView.setText(sectionName);
    ChildRecyclerAdapter childRecyclerAdapter = new ChildRecyclerAdapter(items);
    holder.recyclerChild.setAdapter(childRecyclerAdapter);
    childRecyclerAdapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(String item) {
            // TODO: 07/02/2022 handle click

        }
    });

}

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


public static class MainViewHolder extends RecyclerView.ViewHolder {

    TextView sectionNameTextView;
    RecyclerView recyclerChild;

    public MainViewHolder(final View itemView) {
        super(itemView);

        sectionNameTextView = itemView.findViewById(R.id.txt_section_name);
        recyclerChild = itemView.findViewById(R.id.child_recyclerview);
        LinearLayoutManager layoutManager = new LinearLayoutManager(itemView.getContext());
        recyclerChild.setLayoutManager(layoutManager);

    }
}

}

//OnItemClickListener

public interface OnItemClickListener {

void onItemClick(String item);

}


Solution

  • You can simple make one more interface and call it in nested adapter's onclick method.

    So it will pass that data from adapter to the activity when you click any adapter items.

    Like this :

    1. Create an interface for getting the child recyclerview item click in the activity or fragment.

    First, you need to change your child adapter's click listener from this

    public interface OnItemClickListener {
        void onItemClick(String item);
    }
    

    to this :

    public interface OnItemClickListener {
        void onItemClick(int childPosition);
    }
    

    then pass the adapter position of child recyclerview instead of string value.

    Now, make a new interface to get both the parent and child item clicks in the activity or fragment.

    public interface RvItemClickListener {
        void onChildItemClick(int parentPosition, int childPosition, String item);
    }
    

    2. Define the listener and call it on child item click in parent recyclerview adapter :

    RvItemClickListener rvItemClickListener;
        
    public void setRvItemClickListener(RvItemClickListener rvItemClickListener){
        this.rvItemClickListener = rvItemClickListener;
    }
    

    3. Call it on child item click :

    childRecyclerAdapter.setOnItemClickListener(new OnItemClickListener() {
                    @Override
                    public void onItemClick(int childPosition) {
                        String item = items.get(childPosition);
                        rvItemClickListener.onChildItemClick(getAdapterPosition(), childPosition, item);
                      }
                   });
    

    4. The last step is to override the method in your activity or fragment as you do it normally :

    @Override
    public void onItemClick(int parentPosition, int childPosition, String item) {
    
    }
    

    I hope it's enough for you to understand what I am trying to say.

    It's just an example. Do make changes as per your needs.