RecyclerView多级目录实现

项目中用到了多级的目录,我因此自己参考了些资料并去总结了写RecyclerView多级条目的方式!写下自己的总结。

实现方式不外乎两种:
1,多级嵌套recyclerview
2,多种Type的item的实现方式

一,第一种我们是经常用到,两级嵌套的时候感觉很好使用,但是嵌套的级数更多的话,实现起来也就麻烦了,特别是三级或者更多级的时候,你会写到欲仙欲死的!
二,第二种就是我们常用的多种Type的条目,使用方式很多种,满足各种需求!
以下两种情况适合你大多数的项目的!当然,你要自己看,也就能自己很随意写出RecyclerView的多级目录了
1),这里我实现 省 与 城市的选择的多级
这里是比较少的数据,而且这里的数据都是默认展开的!已经实现单一条目的 单选!!!

这里写图片描述

public class SearchPositionSortAdapter extends RecyclerView.Adapter<ExampleViewHolder> {

    public static final int TYPE_TITLE = 0;
    public static final int TYPE_CITY = 1;

    private SparseArray<SelectBean> mSparseArray;

    private final Context context;

    private List<String> cityTitle;// 城市拼音字母数据
    private List<List<String>> cityNames;
        // 传入两个集合,这里你根据自己需要参数
        // 第一个参数为第一级目录,第二个参数为第二级目录
    public SearchPositionSortAdapter(Context context, List<String> cityTitle, List<List<String>> map) {
        this.context = context;
        this.cityTitle = cityTitle;
        cityNames = map;
        mSparseArray = new SparseArray<>();
    }

    private SparseArray getCurrentChooseItem() {
        return mSparseArray;
    }

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

        switch (viewType) {
            case TYPE_TITLE:
                return new CityTitleHolder(R.layout.item_choose_location_title, parent, viewType, 100);

            case TYPE_CITY:
                return new CityNameHolder(R.layout.item_choose_location_cityname, parent, viewType);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(ExampleViewHolder holder, int position) {
        if (holder instanceof CityNameHolder) {
            holder.refreshData(cityNames.get(position / 2), position);
        } else if (holder instanceof CityTitleHolder) {
            holder.refreshData(cityTitle.get(position / 2), position);
        }
    }

    @Override
    public int getItemCount() {
        return cityTitle.size() * 2;
    }

    @Override
    public int getItemViewType(int position) {
        if (position % 2 == 0) {
            return TYPE_TITLE;
        } else {
            return TYPE_CITY;
        }
    }

//    ===================ViewHolder======================

    /**
     * GridView形状的RecyclerView
     */
    class CityNameHolder extends ExampleViewHolder<List<String>> {
        RecyclerView revCityname;

        private List<String> data;

        public CityNameHolder(int viewId, ViewGroup parent, int viewType) {
            super(viewId, parent, viewType);
            this.revCityname = (RecyclerView) itemView.findViewById(R.id.rev_cityname);
        }


        @Override
        public void refreshData(List<String> data, int position) {
            super.refreshData(data, position);
            this.data = data;
            revCityname.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
            //  某一行的id
            GridAdapter gridAdapter = new GridAdapter(position);
            revCityname.setAdapter(gridAdapter);
        }

        private class GridAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
            // 这一行的 id
            private int CurrenIndex;

            public GridAdapter(int Currentpos) {
                super();
                this.CurrenIndex = Currentpos;
            }

            @Override
            public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                final CityTitleHolder cityTitleHolder = new CityTitleHolder(R.layout.item_gridview_cityname, parent, viewType, CurrenIndex);
                cityTitleHolder.title.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // 拿到当前的 对象
                        SelectBean mSelectbean = new SelectBean(cityTitleHolder.getAdapterPosition(), cityTitleHolder.title.getText().toString());
                        // 没有选中的
                        if (mSparseArray.get(CurrenIndex) == null) {
                            mSparseArray.put(CurrenIndex, mSelectbean);
                        } else {      // 有选中的
                            if (mSparseArray.get(CurrenIndex).equals(mSelectbean)) {
                                mSparseArray.remove(CurrenIndex);
                            } else {
                                mSparseArray.remove(CurrenIndex);
                                mSparseArray.put(CurrenIndex, mSelectbean);
                            }
                        }
                        // 点击完首先当前界面
                        notifyDataSetChanged();
                    }
                });
                return cityTitleHolder;
            }

            @Override
            public void onBindViewHolder(ExampleViewHolder holder, int position) {
                holder.refreshData(data.get(position), position);
            }

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

    /**
     * 普通条目hodler
     */
    private class CityTitleHolder extends ExampleViewHolder<String> {
        //        当前行的index ;
        private int CurrentIndex;
        private TextView title;

        public CityTitleHolder(int viewId, ViewGroup parent, int viewType, int posIndex) {
            super(viewId, parent, viewType);
            title = (TextView) itemView.findViewById(R.id.title);
            CurrentIndex = posIndex;
//            ViewGroup.LayoutParams layoutParams = title.getLayoutParams();
//            layoutParams.width = layoutParams.height = DisplayUtil.getScreenWidth(context) / 3;
//            title.setLayoutParams(layoutParams);
        }

        //if (mSparseArray.get(CurrentIndex).getCurrentPos() == position && mSparseArray.get(CurrentIndex).getCurrentData().equals(data))
        @Override
        public void refreshData(String data, int position) {
            super.refreshData(data, position);
            if (CurrentIndex % 2 == 1) {
                if (mSparseArray.get(CurrentIndex) != null && mSparseArray.get(CurrentIndex).equals(new SelectBean(position, data))) {
                    title.setTextColor(context.getResources().getColor(R.color.app_focus));
                    title.setBackgroundResource(R.drawable.shape_gridview_item_select);
                } else {
                    title.setTextColor(context.getResources().getColor(R.color.text_color2));
                    title.setBackgroundResource(R.drawable.shape_gridview_item);
                }
               /* if (mSparseArray.get(CurrentIndex) == null) {
                    title.setTextColor(context.getResources().getColor(R.color.text_color2));
                    title.setBackgroundResource(R.drawable.shape_gridview_item);
                } else {

                }*/

            }
            title.setText(data);
//            mSparseArray.
        }
    }

}

2),这里实现的专业选择大全,这里是三级目录的实现其实和上面实现原理差不多一致! 这里最烦的是数据结构,我随便写了个简单的格式,你参照这个格式和服务器的哥们讨论吧
这里是可对应多种的数据结构,灵活多变!易于改造!因为我是先写的上面,再写的这个Adapter,不然这个完全够使用任何的形式(单选,多选,动画弹出)的adapter!

这里写图片描述

数据结构

/**
 * @data 2017/4/12 0012
 * @aurher Administrator
 */

public class ThreeItemInfo {

    private String status = "1";
    private boolean isExpading ;
    private List<ThreeItemInfo> results = new ArrayList<>();


    public boolean getIsExpading(){
        return isExpading ;
    }
    public void setIsExpading(boolean isExpading){
        this.isExpading = isExpading ;
    }
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public List<ThreeItemInfo> getResults() {
        return results;
    }

    public void setResults(List<ThreeItemInfo> results) {
        this.results = results;
    }


}

模拟数据

      mList = new ArrayList<>();
        for (int i = 0; i <= 5; i++) {
            ThreeItemInfo threeItemInfo = new ThreeItemInfo();
            threeItemInfo.setStatus("1");
            if (i % 2 == 0) {
                List<ThreeItemInfo> itemInfos = new ArrayList<>();
                for (int j = 0; j <= 5; j++) {
                    ThreeItemInfo threeItemInfo_2 = new ThreeItemInfo();
                    threeItemInfo_2.setStatus("2");
                    itemInfos.add(threeItemInfo_2);
                    if (j % 2 == 0) {
                        List<ThreeItemInfo> itemInfos_list = new ArrayList<>();
                        for (int z = 0; z <= 5; z++) {
                            ThreeItemInfo threeItemInfo_3 = new ThreeItemInfo();
                            threeItemInfo_3.setStatus("3");
                            itemInfos_list.add(threeItemInfo_3);
                        }
                        // 二级目录的添加
                        threeItemInfo_2.setResults(itemInfos_list);
                    }
                }
                // 二级目录的添加
                threeItemInfo.setResults(itemInfos);
            }
            // 添加一级目录
            mList.add(threeItemInfo);
        }
public class ThreeItemAdapter extends MultiItemRecycleViewAdapter<ThreeItemInfo> {
    private static final int TYPE_ONE = 0;
    private static final int TYPE_TWO = 1;
    private static final int TYPE_THREE = 2;

    public ThreeItemAdapter(Context context, List<ThreeItemInfo> datas) {
        super(context, datas, new MultiItemTypeSupport<ThreeItemInfo>() {
            @Override
            public int getLayoutId(int itemType) {
                int i = 0;
                switch (itemType) {
                    case TYPE_ONE:
                        i = R.layout.item_one_threeitem;
                        break;
                    case TYPE_TWO:
                        i = R.layout.item_two_threeitem;
                        break;
                    case TYPE_THREE:
                        i = R.layout.item_three_threeitem;
                        break;
                }
                return i;
            }

            @Override
            public int getItemViewType(int position, ThreeItemInfo threeItemInfo) {
                String currentCity = threeItemInfo.getStatus();
                int i = 0;
                switch (currentCity) {
                    case "1":
                        i = TYPE_ONE;
                        break;
                    case "2":
                        i = TYPE_TWO;
                        break;
                    case "3":
                        i = TYPE_THREE;
                        break;

                }
                return i;
            }
        });
    }

    @Override
    public void convert(ViewHolderHelper helper, ThreeItemInfo threeItemInfo, int position) {
        switch (helper.getLayoutId()) {
            case R.layout.item_one_threeitem:
                bindViewOne(helper, threeItemInfo, position);
                break;
            case R.layout.item_two_threeitem:
                bindViewTwo(helper, threeItemInfo, position);
                break;
            case R.layout.item_three_threeitem:
                bindViewThree(helper, threeItemInfo, position);
                break;
        }
    }

    private void bindViewOne(ViewHolderHelper helper, final ThreeItemInfo threeItemInfo, final int position) {
        TextView tv_1 = helper.getView(R.id.tv_1);
        helper.getConvertView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LogUtils.logd("我被点击了");
                LogUtils.logd("我被点击了----" + (threeItemInfo.getResults()) + "-----" + threeItemInfo.getResults().size() + "---------" + threeItemInfo.getIsExpading());
                if (threeItemInfo.getResults() != null && threeItemInfo.getResults().size() != 0 && threeItemInfo.getIsExpading()) {
                    addAllAt(position + 1, threeItemInfo.getResults());
                    threeItemInfo.setIsExpading(false);
                } else if (threeItemInfo.getResults() != null & threeItemInfo.getResults().size() != 0 && !threeItemInfo.getIsExpading()) {
                    for (ThreeItemInfo item : threeItemInfo.getResults()) {
                        if (!item.getIsExpading()) {
                            removeAll(item.getResults());
                        }
                    }
                    removeAll(threeItemInfo.getResults());
                    threeItemInfo.setIsExpading(true);
                }
            }
        });

    }

    private void bindViewTwo(ViewHolderHelper helper, final ThreeItemInfo threeItemInfo, final int position) {
        TextView tv_2 = helper.getView(R.id.tv_2);
        helper.getConvertView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (threeItemInfo.getResults() != null && threeItemInfo.getResults().size() != 0 && threeItemInfo.getIsExpading()) {
                    addAllAt(position + 1, threeItemInfo.getResults());
                    threeItemInfo.setIsExpading(false);
                } else if (threeItemInfo.getResults() != null & threeItemInfo.getResults().size() != 0 && !threeItemInfo.getIsExpading()) {
                    removeAll(threeItemInfo.getResults());
                    threeItemInfo.setIsExpading(true);
                }
            }
        });
    }

    private void bindViewThree(ViewHolderHelper helper, ThreeItemInfo threeItemInfo, final int position) {
        TextView tv_3 = helper.getView(R.id.tv_3);
        helper.getConvertView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LogUtils.logd("我被点击了" + "我是第三个条目" + position);
                if (onItemThreeClickListener != null) {
                    onItemThreeClickListener.ThreeOnclickListener(position);
                }
            }
        });
    }

    public interface OnItemThreeClickListener {
        void ThreeOnclickListener(int position);
    }

    private OnItemThreeClickListener onItemThreeClickListener;

    public void setOnItemThreeClickListener(OnItemThreeClickListener onItemThreeClickListener) {
        this.onItemThreeClickListener = onItemThreeClickListener;
    }
}

可能上面没写得很清楚,我附带源码上传吧!
封装了完整的Adapter,已经自己单独写了第一gif的截图!希望能帮到你写多级目录(第二个Gif是默认生成的)
DemoAdapter

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值