recycleview实现分组列表

最近看到diycodeAPP中一个列表分组界面,起初是用listview嵌套gridview实现的,效果一样只是有些复杂,但是后来看了下源码,是用recycleview实现的,并且还很简单,

最后就尝试了一下,实现了这个列表功能,所以在这里记录一下,方便以后遇到类似功能,直接可以拿来使用,这里感谢一下diycode的API以及实体类,为了方便接口和实体类直接用diycode的,API:https://diycode.cc/api/v3/sites.json

看下效果图吧

image.png

1、实体类

public class Sites implements Serializable {
   
 
    private String name;
    private int id;
    private List<Site> sites;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public List<Site> getSites() {
        return sites;
    }
 
    public void setSites(List<Site> sites) {
        this.sites = sites;
    }
 
    public static class Site implements Serializable {
        /**
         * name : botlist
         * url : http://botlist.co
         * avatar_url : https://favicon.b0.upaiyun.com/ip2/botlist.co.ico
         */
 
        private String name;
        private String url;
        private String avatar_url;
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
 
        public String getUrl() {
            return url;
        }
 
        public void setUrl(String url) {
            this.url = url;
        }
 
        public String getAvatar_url() {
            return avatar_url;
        }
 
        public void setAvatar_url(String avatar_url) {
            this.avatar_url = avatar_url;
        }
    }
}

2、适配器

/**
 * @ProjectName: DiycodeApp
 * @PackageName: com.wenjie.diycode.adapter
 * @FileName: com.wenjie.diycode.adapter.SitesAdapter.java
 * @Author: wenjie
 * @Date: 2017-08-17 14:57
 * @Description:
 * @Version:
 */
public class SitesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
 
    public static final int SITES = 0;//标题 跨一列 也就是合并两列
    public static final int SITE = 1;//不跨列
    //所有数据的集合,将标题和数据项,全部装在到这个集合中,在适配器中利用viewtype来区分,并显示不同的布局
    private List<Object> items = new ArrayList<>();
    private Context context;
 
    public SitesAdapter(Context context, List<Object> items) {
        this.items = items;
        this.context = context;
    }
 
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater mInflater = LayoutInflater.from(context);//获取mInflater对象
        switch (viewType) {//根据viewtyupe来区分,是标题还是数据项
            case SITES://标题,加载显示标题的item布局,就一个textview显示文本,这里我们自顶一个标题的viewholder->SitesHolder
                final SitesHolder sitesHolder = new SitesHolder(mInflater.inflate(R.layout.item_sites, parent, false));
                //点击事件
                sitesHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(onItemClickListener != null){
                            onItemClickListener.onClick(sitesHolder.itemView , sitesHolder.getLayoutPosition());
                        }
                    }
                });
                return sitesHolder;
            case SITE://数据项,雷同不赘述了,标题和数据项的item布局和veiwholder都不会相互影响的
                final SiteHolder siteHolder = new SiteHolder(mInflater.inflate(R.layout.item_site, parent, false));
                siteHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(onItemClickListener != null){
                            onItemClickListener.onClick(siteHolder.itemView , siteHolder.getLayoutPosition());
                        }
                    }
                });
                return siteHolder;
        }
        return null;
    }
 
    @Override
    public int getItemViewType(int position) {
        //这个方法很重要,这里根据position取出items集合中的对象,用instanceof判断他是标题还是数据项,来返回对应的标识
        if (items.get(position) instanceof Sites) {//根据items数据类型的不同来判断他是标题还是数据项
            return SITES;//标题
        } else if (items.get(position) instanceof Sites.Site) {
            return SITE;//数据项
        } else {
            return -1;
        }
    }
 
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
        //根据getItemViewType绑定view进行赋值显示
        switch (holder.getItemViewType()) {
            case SITES://标题
                SitesHolder sitesHolder = (SitesHolder) holder;
                sitesHolder.name.setText(((Sites) items.get(position)).getName());
                break;
            case SITE://数据项
                SiteHolder siteHolder = (SiteHolder) holder;
                siteHolder.name.setText(((Sites.Site) items.get(position)).getName());
                Glide.with(context).load(((Sites.Site) items.get(position)).getAvatar_url()).into(siteHolder.icon);
                break;
        }
    }
 
    /**
     * 公布点击事件出去
     */
    private OnItemClickListener onItemClickListener;
 
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        this.onItemClickListener = onItemClickListener;
    }
 
    public interface OnItemClickListener{
        void onClick(View itemview , int position);
    }
 
    @Override
    public int getItemCount() {
        return items.size();
    }
 
    /**
     * 数据项的viewholder  一个文本textview一个cion  imageview
     */
    private class SiteHolder extends RecyclerView.ViewHolder {
 
        TextView name;
        ImageView icon;
 
        SiteHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
            icon = (ImageView) itemView.findViewById(R.id.icon);
        }
    }
 
    /**
     * 标题的viewholder  只有一个textview
     */
    private class SitesHolder extends RecyclerView.ViewHolder {
 
        TextView name;
 
        SitesHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
        }
    }
}

接下来就是 当数据获取成功之后,如何和适配器进行绑定显示sites就是从获取获取到了并解析好的数据集合

List<Object> items = new ArrayList<>();
        //数据获取之后  将数据循环遍历,放进items集合中,至于服务器返回什么格式的数据,我想看下实体类就应该明白了
        for (int i=0; i < sites.size(); i++){
            items.add(sites.get(i));
            for(int k = 0; k < sites.get(i).getSites().size(); k ++){
                items.add(sites.get(i).getSites().get(k));
            }
        }
        //实例化适配器将遍历好的数据放进适配器中
        sitesAdapter = new SitesAdapter(getActivity() ,items);
        //new一个布局管理器,这里是用GridLayoutManager,要区分3列
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity() , 3);//多少列,如果数据项只需要1列,这里写1,下面return 也返回1即可实现
        //下面这个方法很重要,根据position获取当前这条数据是标题还是数据项,来设置他的跨列
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                //适配器中有这么一个方法,根据position获取当前这条数据是标题还是数据项,来设置他的跨列
                switch (sitesAdapter.getItemViewType(position)){
                    case SitesAdapter.SITES://标题的话跨多少列 这个值要跟整个列数相等 如果大于会出错,小于布局会乱
                        return 3;
                    case SitesAdapter.SITE://数据项
                        return 1;//不跨列,就是分成三列显示
                    default:
                        return -1;
                }
            }
        });
        sitesRecycleView.setLayoutManager(gridLayoutManager);
//        sitesRecycleView.addItemDecoration(new DividerItemDecoration(getActivity() , GridLayoutManager.VERTICAL));
        sitesRecycleView.setAdapter(sitesAdapter);
 
        //item的点击事件,这里实现,进行具体的操作
        sitesAdapter.setOnItemClickListener(new SitesAdapter.OnItemClickListener() {
            @Override
            public void onClick(View itemview, int position) {
                switch (sitesAdapter.getItemViewType(position)){
                    case SitesAdapter.SITE:
//                        ToastUtils.showToast(getActivity() , ((CoolSites.Site) items.get(position)).getName());
                        Intent intent = new Intent(getActivity() , WebViewActivity.class);
                        intent.putExtra("url" , ((Sites.Site) items.get(position)).getUrl());
                        startActivity(intent);
                        break;
                    case SitesAdapter.SITES:
                        ToastUtils.showToast(getActivity() , ((Sites) items.get(position)).getName());
                        break;
                }
            }
        });
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • https://blog.csdn.net/csdn576038874/article/details/77648...
    利之见阅读 3,389评论 0 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,563评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,471评论 2 59
  • 直到今天偷偷地躲到某栋居民楼的楼顶,一屁股坐在垫着广告纸的地上,啃着昨天买的面包以及绿豆饼,我才终于肯真的让...
    昭朝阅读 221评论 0 0
  • 我初中的宿舍楼很简陋。叫作宿舍楼,有四层,其实只有一层可以住宿。一楼是面向街道的商店,二楼是外租房,三楼是教师的家...
    7次遇见我阅读 397评论 0 3