最近看到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; } } });
作者:渐行渐远j
链接:https://www.jianshu.com/p/de0467ffc983