最近写的一个商城APP,布局比较复杂,其中有需要使用到Recyclerview嵌套RecyclerView的地方。 另外,本例子使用的Adapter框架为BaseQuickAdapter 。如果有使用到其他的Adapter框架需要自己适当修改。
BaseQuickAdapter 框架 Github地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper
红色部分是一个Recyclerview 蓝色部分又是一个RecyclerView。Adapter加载的数据格式应该是List<data>,其中data又是一个List。当用户点击内层recyclerview时需要获取第一层的List的Position又要获取第二层的List的Positon。为了实现该效果,我们有两个方法,先介绍第一种方法:
在外层RecyclerView的Adapter中添加接口,供Activity或Fragment使用:
public class FirstAdapter extends BaseQuickAdapter<MyFirstList,BaseViewHolder> {
private OnChildClickListener onItemClickListener;
public FirstAdapter (int layoutResId,@Nullable List data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, MyFirstList item) {
if (item.getSecondlist().size()!=0){
SecondAdapter secondadapter =new SecondAdapter (R.layout.item_second,item.getSecondlist()); //加载内层RecyclerView的布局与数据
secondadapter.setLayoutManager(new GridLayoutManager(mContext,3));
secondadapter.setAdapter(secondadapter );
secondadapter.addOnItemTouchListener(new com.chad.library.adapter.base.listener.OnItemClickListener() { //OnItemClickListener为BaseRecyclerView的子控件监听方法
@Override
public void onSimpleItemClick(BaseQuickAdapter adapter, View view,int position) {
onItemClickListener.success(position);
}
});
}
}
public void setOnChildPositionListener(OnChildClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
public interface OnChildClickListener{
//成功的方法传 int 的索引
void success(int index);
}
}
在Activity或Fragment中填充外层RecyclerView数据:
RecyclerView firstview= (RecyclerView) findViewById(R.id.recyclerview);
FirstAdapter firsrtAdapter= new FirstAdapter (R.layout.item_first,MyFirstList);
firstview.setLayoutManager(new LinearLayoutManager(mContext));
firstview.setAdapter(classificationListTwoAdapter);
firstview.addOnItemTouchListener(new OnItemClickListener() {
@Override
public void onSimpleItemClick(BaseQuickAdapter adapter, View view, int position) {
firsrtAdapter.setOnChildPositionListener(new ClassificationListTwoAdapter.OnChildClickListener() {
@Override
public void success(int index) {
MyFirstList.get(position).getSecondlist().get(index) //获取内层RecyclerView数据
}
});
}
});
然后介绍第二种方法,该方法主要是根据控件嵌套控件的点击事件触发逻辑去实现获取内层数据的效果,但是也需要在外层Recyclerview的Adapter中添加接口供Activity使用:
public class FirstAdpter extends BaseQuickAdapter<MyFirstList , BaseViewHolder> {
int position ;
private OnChildClickListener onItemClickListener;
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public FirstAdpter (int layoutResId, @Nullable List<MyFirstList > data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, MyFirstList item) {
RecyclerView recyclerView = helper.itemView.findViewById(R.id.rv_item_recommend);
helper.addOnClickListener(R.id.rv_item_recommend); //给内层RecyclerView增加点击事件
SecondAdapter secondadpter= new SecondAdapter (R.layout.item_item_recommend,item.getList());
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
secondadpter.setOnItemClickListener((adapter, view1, position1) -> {
onItemClickListener.success(position1,position);
});
recyclerView.setAdapter(secondadpter);
}
public void setOnChildPositionListener(OnChildClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
public interface OnChildClickListener{
//成功的方法传 int 的索引
void success(int index,int position);
}
}
在Activity或Fragment中填充外层RecyclerView数据:
//MyData为最外层的List数据
RecyclerView firstview= (RecyclerView) findViewById(R.id.recyclerview)
FirstAdapter firstadapter= new FirstAdapter (R.layout.item_first, MyData);
firstview.addOnItemTouchListener(new OnItemChildClickListener() {
@Override
public void onSimpleItemChildClick(BaseQuickAdapter adapter, View view, int position) {
firstadapter.setPosition(position);
}
});
firstadapter.setOnChildPositionListener(new FirstAdapter.OnChildClickListener() {
@Override
public void success(int index,int positon) {
MyData.get(positon).getSecondlist().get(index); //获取内层 Recyclerview数据
}
});
firstview.setLayoutManager(new LinearLayoutManager(mContext));
firstview.setAdapter(firstadapter);
PS:
Recyclerview嵌套Recyclerview中,若在首个recyclerview中的onBindViewHolder方法里(若使用了BRAH,则是在convert()方法中),通过addOnItemTouchListener设置了第二个recyclerview的点击事件,则需要在onBindViewHolder()添加判断条件,防止外层Activity或Fragment中,调用第一个Recyclerview的notifyDataSetChanged()方法后,重复设置点击事件导致子Recyclerview的点击事件被重复触发。
public class FirsrAdapter extends BaseQuickAdapter<xxx, BaseViewHolder> {
private boolean setclick = false;
......
@Override
protected void convert(BaseViewHolder helper, xxx) {
SecondAdapter secondadapter = new SecondAdapter(xxx,xxx);
if (!setclick) {
setclick = true;
secondadapter.addOnItemTouchListener(...)
}
}
}