https://blog.csdn.net/csdn576038874/article/details/77648366
最近看到diycodeAPP中一個列表分組界面,起初是用listview嵌套gridview實現(xiàn)的,效果一樣只是有些復雜,但是后來看了下源碼,是用recycleview實現(xiàn)的,并且還很簡單,
最后就嘗試了一下,實現(xiàn)了這個列表功能,所以在這里記錄一下,方便以后遇到類似功能,直接可以拿來使用,這里感謝一下diycode的API以及實體類,為了方便接口和實體類直接用diycode的,API:https://diycode.cc/api/v3/sites.json
看下效果圖吧
1、實體類
[java] view plaincopy
<embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_1" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent" style="box-sizing: border-box;">
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、適配器
[java] view plaincopy
<embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_2" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent" style="box-sizing: border-box;">
/**
- @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;//不跨列
//所有數(shù)據(jù)的集合,將標題和數(shù)據(jù)項,全部裝在到這個集合中,在適配器中利用viewtype來區(qū)分,并顯示不同的布局
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) {//根據(jù)viewtyupe來區(qū)分,是標題還是數(shù)據(jù)項
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://數(shù)據(jù)項,雷同不贅述了,標題和數(shù)據(jù)項的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) {
//這個方法很重要,這里根據(jù)position取出items集合中的對象,用instanceof判斷他是標題還是數(shù)據(jù)項,來返回對應的標識
if (items.get(position) instanceof Sites) {//根據(jù)items數(shù)據(jù)類型的不同來判斷他是標題還是數(shù)據(jù)項
return SITES;//標題
} else if (items.get(position) instanceof Sites.Site) {
return SITE;//數(shù)據(jù)項
} else {
return -1;
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
//根據(jù)getItemViewType綁定view進行賦值顯示
switch (holder.getItemViewType()) {
case SITES://標題
SitesHolder sitesHolder = (SitesHolder) holder;
sitesHolder.name.setText(((Sites) items.get(position)).getName());
break;
case SITE://數(shù)據(jù)項
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();
}
/**
- 數(shù)據(jù)項的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);
}
}
}
接下來就是 當數(shù)據(jù)獲取成功之后,如何和適配器進行綁定顯示
sites就是從獲取獲取到了并解析好的數(shù)據(jù)集合
[java] view plaincopy
<embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_3" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent" style="box-sizing: border-box;">
List<Object> items = new ArrayList<>();
//數(shù)據(jù)獲取之后 將數(shù)據(jù)循環(huán)遍歷,放進items集合中,至于服務器返回什么格式的數(shù)據(jù),我想看下實體類就應該明白了
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));
}
}
//實例化適配器將遍歷好的數(shù)據(jù)放進適配器中
sitesAdapter = new SitesAdapter(getActivity() ,items);
//new一個布局管理器,這里是用GridLayoutManager,要區(qū)分3列
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity() , 3);//多少列,如果數(shù)據(jù)項只需要1列,這里寫1,下面return 也返回1即可實現(xiàn)
//下面這個方法很重要,根據(jù)position獲取當前這條數(shù)據(jù)是標題還是數(shù)據(jù)項,來設置他的跨列
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//適配器中有這么一個方法,根據(jù)position獲取當前這條數(shù)據(jù)是標題還是數(shù)據(jù)項,來設置他的跨列
switch (sitesAdapter.getItemViewType(position)){
case SitesAdapter.SITES://標題的話跨多少列 這個值要跟整個列數(shù)相等 如果大于會出錯,小于布局會亂
return 3;
case SitesAdapter.SITE://數(shù)據(jù)項
return 1;//不跨列,就是分成三列顯示
default:
return -1;
}
}
});
sitesRecycleView.setLayoutManager(gridLayoutManager);
// sitesRecycleView.addItemDecoration(new DividerItemDecoration(getActivity() , GridLayoutManager.VERTICAL));
sitesRecycleView.setAdapter(sitesAdapter);
//item的點擊事件,這里實現(xiàn),進行具體的操作
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;
}
}
});