RecyclerView之多层嵌套

本文基于baseRecyclerView依赖库.
先来看效果图:
这里写图片描述
首先,添加依赖:

compile 'com.android.support:design:26.0.0-alpha1'
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.25'

首先,先写一个简单的布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

再写三个item的布局,最外层到最内层分别为红绿蓝.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:background="#ff0000"
              android:orientation="vertical">
    <TextView
        android:id="@+id/tv_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

我们需要分别为每个item写javabean.
OneBean.java

public class OneBean extends AbstractExpandableItem<TwoBean> implements MultiItemEntity {
    private String textOne;

    public String getTextOne() {
        return textOne;
    }

    public void setTextOne(String textOne) {
        this.textOne = textOne;
    }

    /**
     * javabean中需要绑定adapter中addItemType的类型(这是为了在adapter中的convert中进行区分)
     * @return
     */
    @Override
    public int getItemType() {
        return MainAdapter.TYPE_LEVEL_0;
    }

    /**
     * 从第几个item开始里边有嵌套,默认是0,从第一个开始
     * @return
     */
    @Override
    public int getLevel() {
        return 0;
    }

最外层的javabean,由于里边嵌套着第二层的javabean,所以继承的AbstractExpandableItem<TwoBean>

TwoBean.java

public class TwoBean extends AbstractExpandableItem<ThreeBean> implements MultiItemEntity {
    private String textTwo;

    public String getTextTwo() {
        return textTwo;
    }

    public void setTextTwo(String textTwo) {
        this.textTwo = textTwo;
    }

    @Override
    public int getItemType() {
        return MainAdapter.TYPE_LEVEL_1;
    }

    @Override
    public int getLevel() {
        return 0;
    }
}

ThreeBean.java

public class ThreeBean implements MultiItemEntity {

    private String textThree;

    public String getTextThree() {
        return textThree;
    }

    public void setTextThree(String textThree) {
        this.textThree = textThree;
    }

    @Override
    public int getItemType() {
        return MainAdapter.TYPE_LEVEL_2;
    }
}

由于最内层的里边不会嵌套了,就不需要继承AbstractExpandableItem 了.

下面,来看MainAdapter的代码:

public class MainAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> {
    //继承BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> 是固定写法,因为javabean中都实现了MultiItemEntity

    public static final int TYPE_LEVEL_0 = 0;
    public static final int TYPE_LEVEL_1 = 1;
    public static final int TYPE_LEVEL_2 = 2;

    public MainAdapter(List<MultiItemEntity> data) {
        super(data);
        //初始化adapter的时候把所有嵌套的布局都添加上
        addItemType(TYPE_LEVEL_0,R.layout.item_one);//第一层布局(最外层)
        addItemType(TYPE_LEVEL_1,R.layout.item_two);//第二层布局
        addItemType(TYPE_LEVEL_2,R.layout.item_three);//第三层布局
    }

    @Override
    protected void convert(final BaseViewHolder helper, MultiItemEntity item) {
        switch (helper.getItemViewType()) {
            case TYPE_LEVEL_0 :  //第一层布局
                final OneBean oneBean = (OneBean) item;
                //设置最外层 数据+位置(位置不能用getLayoutPosition方法,因为getLayoutPosition方法得到的位置是包含了整个的item位置从外层到里层依次数,而我们要的位置是这一层的位置)
                helper.setText(R.id.tv_one,oneBean.getTextOne() + helper.getAdapterPosition());
                //设置点击外层item展开或关闭里边的item(固定写法)
                helper.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //得到点击位置
                        int position = helper.getAdapterPosition();
                        if(oneBean.isExpanded()) {
                            //item是展开的
                            //关闭对应的item
                            collapse(position);
                        }else {
                            //item是关闭的,展开item
                            expand(position);
                        }
                    }
                });
                break;
            case TYPE_LEVEL_1: //第二层布局
                final TwoBean twoBean = (TwoBean) item;
                //设置第二层外层 数据+位置
                helper.setText(R.id.tv_two,twoBean.getTextTwo() + helper.getAdapterPosition());
                //设置点击第二层item展开或关闭第二层里边的item
                helper.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //得到点击位置
                        int position = helper.getAdapterPosition();
                        if(twoBean.isExpanded()) {
                            //item是展开的
                            //关闭对应的item
                            collapse(position,false);
                        }else {
                            //item是关闭的,展开item
                            expand(position,false);
                        }
                    }
                });
                break;
            case TYPE_LEVEL_2: //第三层布局
                ThreeBean threeBean = (ThreeBean) item;
                //设置最内层 数据+位置
                helper.setText(R.id.tv_three,threeBean.getTextThree() + helper.getAdapterPosition());
                //设置里层的点击事件
                helper.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //得到点击位置
                        int position = helper.getAdapterPosition();
                        Toast.makeText(mContext, ("点击了最内层的item"+position), Toast.LENGTH_SHORT).show();
                    }
                });
                break;
        }
    }
}

下面,来看activity中的代码:

public class MainActivity extends Activity {

    private RecyclerView rv;
    private List<MultiItemEntity> mData;

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

    private void initView() {
        rv = (RecyclerView) findViewById(R.id.rv);
        //初始化数据
        initData();

        final MainAdapter adapter = new MainAdapter(mData);
        //设置整体的layoutmanager
        final GridLayoutManager manager = new GridLayoutManager(this, 3);
        //如果内外层的layoutmanager不一样呢? 需要设置setSpanSizeLookup
        manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                //如果等于最内层,分别设置为1,就是每行3个;如果不是最内层,就设置每行的总个数,也就是一个item占满一行
                return adapter.getItemViewType(position) == MainAdapter.TYPE_LEVEL_2 ? 1 : manager.getSpanCount();
            }
        });
        rv.setAdapter(adapter);
        //设置manager必须放在setAdapter之后,否则setSpanSizeLookup方法不生效
        rv.setLayoutManager(manager);

        //设置三级嵌套全部展开
        adapter.expandAll();
    }

    private void initData() {
        mData = new ArrayList<>();

        int oneCount = 3;
        int twoCount = 2;
        int threeCount = 6;

        for (int i = 0; i < oneCount; i++) {
            //最外层数据
            OneBean oneBean = new OneBean();
            oneBean.setTextOne("我是最外层数据");

            for (int i1 = 0; i1 < twoCount; i1++) {
                //第二层数据
                TwoBean twoBean = new TwoBean();
                twoBean.setTextTwo("我是嵌套在第二层的");

                for (int i2 = 0; i2 < threeCount; i2++) {
                    //最内层数据
                    ThreeBean threeBean = new ThreeBean();
                    threeBean.setTextThree("我是嵌套在最里层的");
                    //最内层数据添加到第二层中
                    twoBean.addSubItem(threeBean);
                }
                //第二层数据添加到第一层中
                oneBean.addSubItem(twoBean);
            }
            //拿到所有数据
            mData.add(oneBean);
        }

    }
}

解释大部分都在代码中,要是看不懂,请看我写的demo:
http://download.csdn.net/download/huchengzhiqiang/9984046

猜你喜欢

转载自blog.csdn.net/huchengzhiqiang/article/details/78019577