getviewtype()实现recyclerview分组

来源:互联网 发布:如何编写js插件 编辑:程序博客网 时间:2024/06/13 14:47

直接进入主题,要实现的效果如下图:
使用的是recyclerview的分组,getviewtype()方法返回不同布局。

这里写图片描述

listview实现就是listview嵌套gridview,把每个分组当成一个listview的一个item,想象就很麻烦,接下来用recycler来实现这个效果。

首先recyclerview的基本用法要会,这里我就不想说recyclerview的基本用法了不太了解的可以看看鸿洋的博客点这里,讲的挺详细的,看完基本使用应该没问题了。

实现思路:

其实以前也做过类似的效果就是用的listview加gridview,所以我才说很麻烦,listview中adapter中有个方法是getItemViewType()根据item返回不同的layout,在getview()中加载不同布局,再来看看那下面的图片,

这里写图片描述

实现一:

首先就是数据list集合。1-8这些所有的数据是放在一个list< Entity >中的,Entity就是服务器返回的数据,只不过在其中加了一个key用于标识当前item是分组还是组员,再根据这个key在getItemViewType()返回不同的type,一般服务器返回的格式如下

{    "resultMsg":{        "groupList":[            {                "childList":[                    {                        "childName":"组员1",                        "openTime":"2017-04-20 11:40:18"                    },                    {                        "childName":"组员2",                        "openTime":"2017-04-20 11:40:18"                    },                    {                        "childName":"组员3",                        "openTime":"2017-04-20 11:40:18"                    }                ],                "groupName":"分组1"            },            {                "childList":[                    {                        "childName":"组员1",                        "openTime":"2017-07-06 10:05:16"                    },                    {                        "childName":"组员2",                        "openTime":"2017-07-06 10:05:16"                    }                ],                "groupName":"分组2"            }        ]    }}

思路二

将上述json数据添加到一个list中,看看上面的数据,一层套着一层,grouplist中套着childlist,一般分组的数据都是这样的json格式。

这里就需要用到map,以key-vale的形式将json数据保存下来,map最好用LinkedHashMap;
LinkedHashMap是有序的存储的你存和取得顺序是一致的,key是groupName; value是组员的list集合,代码如下:

private LinkedHashMap<String, ArrayList<ChildListBean>> groupMap =            new LinkedHashMap<String, ArrayList<ChildListBean>>();

实现三
数据保存下来后就调用adapter的setList()方法刷新数据,在setList()方法方法中遍历map将所有数据添加到一个list中代码如下:

    /**     * @param map     */    public void setList(LinkedHashMap<String, ArrayList<ChildListBean>> map) {        Iterator iterator = map.keySet().iterator();        while (iterator.hasNext()) {            String key = iterator.next().toString();            //遍历数组            if (map.get(key).size() > 0) {            //这里是将group当成一个child一起加到mList中            //也就是mList中包含了group和child,只不过group            //所在的positon有个标识当前position是否为分组                mList.add(new ChildListBean(key, true));            }            mList.addAll(map.get(key));        }        notifyDataSetChanged();    }

再来看看实体类代码,这个有必要贴出来,主要就是ChildListBean 的两个构造方法,如果group还有其他的信息都可以这样加进来,需要什么setXXX什么显示的时候在getXXX,这样就把group信息和child信息添加到一个list中了。

public class GroupChildBean {    private ResultMsgBean resultMsg;    public ResultMsgBean getResultMsg() {        return resultMsg;    }    public void setResultMsg(ResultMsgBean resultMsg) {        this.resultMsg = resultMsg;    }    public static class ResultMsgBean {        private List<GroupListBean> groupList;        public List<GroupListBean> getGroupList() {            return groupList;        }        public void setGroupList(List<GroupListBean> groupList) {            this.groupList = groupList;        }        public static class GroupListBean {            private String groupName;            private List<ChildListBean> childList;            public String getGroupName() {                return groupName;            }            public void setGroupName(String groupName) {                this.groupName = groupName;            }            public List<ChildListBean> getChildList() {                return childList;            }            public void setChildList(List<ChildListBean> childList) {                this.childList = childList;            }            public static class ChildListBean {                private String childName;                private String openTime;                private boolean isGroup;                /**                 * 添加child                 *                 * @param childName                 */                public ChildListBean(String childName) {                    this.childName = childName;                }                /**                 * 把group当成child                 *                 * @param childName                 * @param isGroup                 */                public ChildListBean(String childName, boolean isGroup) {                    this.childName = childName;                    this.isGroup = isGroup;                }                public boolean isGroup() {                    return isGroup;                }                public void setGroup(boolean group) {                    isGroup = group;                }                public String getChildName() {                    return childName;                }                public void setChildName(String childName) {                    this.childName = childName;                }                public String getOpenTime() {                    return openTime;                }                public void setOpenTime(String openTime) {                    this.openTime = openTime;                }            }        }    }}

实现四

有了list集合那就很简单了,接下来就是recyclerview的基本用法了.
就是需要在getViewType中判断是否为分组返回不同的type

@Override    public int getItemViewType(int position) {        if (mList.get(position).isGroup()) {            return GROUP_ITEM_TYPE;        } else {            return CHILD_ITEM_TYPE;        }    }

在onBindViewHolder返回不同的viewHolder

 @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        final ChildListBean bean = mList.get(position);        int type = holder.getItemViewType();        if (type == GROUP_ITEM_TYPE) {            GroupViewHolder holder1 = (GroupViewHolder) holder;            holder1.textView.setText(bean.getChildName());            holder1.cardView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Toast.makeText(mContext, bean.getChildName(), Toast.LENGTH_SHORT).show();                }            });        } else {            ChildViewHolder holder1 = (ChildViewHolder) holder;            holder1.textView.setText(bean.getChildName());            holder1.cardView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Toast.makeText(mContext, bean.getChildName(), Toast.LENGTH_SHORT).show();                }            });        }    }
 /**     * 分组     */    class GroupViewHolder extends RecyclerView.ViewHolder {        TextView textView;        CardView cardView;        public GroupViewHolder(View itemView) {            super(itemView);            textView = (TextView) itemView.findViewById(R.id.header);            cardView = (CardView) itemView.findViewById(R.id.card_view);        }    }    /**     * 成员     */    class ChildViewHolder extends RecyclerView.ViewHolder {        TextView textView;        CardView cardView;        public ChildViewHolder(View itemView) {            super(itemView);            textView = (TextView) itemView.findViewById(R.id.tv);            cardView = (CardView) itemView.findViewById(R.id.card_view);        }    }

在来看看Activity的代码,主要就是initView()中的代码

  private void initView() {        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);        initToolBar(toolbar, "分组recycler", true);        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);        mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));        mAdapter = new GroupRecyAdapter(this);        initData();        mRecyclerView.setAdapter(mAdapter);        mAdapter.setList(groupMap);    }

运行代码效果如下
这里写图片描述

和想象的不一样,因为我们之前是将group当成child一起添加到list中,所以在使用GridLayoutManager并且显示两列的时候并没有判断isGroup这个字段,所以group就跟child一样显示了,这样我们就需要加个判定了,当是group时就让他显示一列,如果是child就让他显示两列,GridLayoutManager有个方法setSpanSizeLookup()就需要我们自己去写了,代码如下,一看就懂

 final GridLayoutManager manager = new GridLayoutManager(this, 2, OrientationHelper.VERTICAL, false);        manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {            @Override            public int getSpanSize(int position) {            //当是group时就让他显示一列,如果是child就让他显示两列                return mAdapter.getItemViewType(position) == GroupRecyAdapter.GROUP_ITEM_TYPE ? manager.getSpanCount() : 1;            }        });        mRecyclerView.setLayoutManager(manager);

manager.getSpanCount()就是上面设置的默认列数

final GridLayoutManager manager = new GridLayoutManager(this, 2, OrientationHelper.VERTICAL, false);

再次运行,完美实现了recyclerview分组的效果。

总结:

recyclerview之所有强大就是因为你完全可以自定义view改如何显示,分组的方法还有很多种,这里只是其中一种。这种实现方式最主要的就两个地方,第一个就是数据处理,将group当成child添加到一个集合list中;第二呢就是 需要重写getSpanSize()方法,判断当前item是否为分组返回不同的列数。这里只有两种type,如果布局更复杂,也可以加,思路差不多。

第一次写这么长的博客,写的有点乱,凑合看吧,如有写的不好的地方希望大佬们指出。有问题可以留言或者加QQ821651400。

源码地址:https://github.com/caobin821651400/Study 在com.example.androidremark.ui2.grouprecycler目录下

这是我的一个小项目,里面包含了好多好的布局或者工具,喜欢的就start下,谢谢~

如果想直接使用可以去github搜MultiType,SLTableView都可以实现,不过封装太好了我是没看懂所以自己想办法写的。

原创粉丝点击