大家好,又见面了,我是你们的朋友全栈君。
一. 实现的效果
实例只是简单的显示了两个分组PC和Mobile两个分组 。
-
两个分组都展开(如下图)
-
第一个分组展开第二个分组收缩(如下图)
-
第一个分组收缩第二个分组展开(如下图)
-
两个分组都收缩(如下图)
二. 简单的一些介绍
1. 万能适配器 具体可以参考http://www.imooc.com/learn/372
1). ViewHolder: 传统的写法我们一般是会把ViewHolder写在Adapter里面,这里把ViewHolder提取出来作为一个公共的类使用这样不用每个Adpater都去写一遍ViewHolder了,所以对于每个ViewHolder类我们要知道的对象有
private SparseArray<View> mViews = null;
private Context mContext = null;
private View mConvertView = null;
private int mPosition = -1;
mViews 用来保存我们每个item布局里面的view对应的key是view的id,mContext 用来保存上下午,mConverView保存对应item的ConvertView,mPosition用来保存item对应的位置。
2). MobileBaseAdapter: 也做了稍微的优化,因为我们在写Adapter里面getView的时候很多动作都是重复的,所以对应重复的动作全部都单独提取出来提前写好了,在使用MobileBaseAdapter的时候只要实现public abstract void convert(ViewHolder viewHolder, T t); 就好了具体可以看下代码中的做法。用起来是非常简单的。
2. 具体分组的实现
我们先要知道BaseAdapter里面的getItemViewType()函数和getViewTypeCount()函数的作用。getViewTypeCount表示ListView 每个item会缓存几个复用对象,getItemViewType则是根据position判断这个这个item对应用哪个缓存的对象,换句话说比如getViewTypeCount返回的值是3,那么每个item可能就会有0,1,2三个缓存复用的对象,这个时候getItemViewType返回的是0,这样就会用0这个对象去复用。
这样我们在来看下MobileCategoryAdapter里面的代码。
1). 内部类Category 这个没什么东西包含一个BaseAdapter对象和一些必要的方法, 因为我们在MobileCategoryAdatper里面肯定是会有List对象的。
2). 内部类CategoryListClickListener 实现了ListView的OnItemClickListener。因为我们要ListView.setOnClickListener这个类的对象。
在这个类中我们会区分当前点击的是title(点击的时候我们可能会展开和收缩该分组)还是item。然后把title(onTitleClick)和item(onItemClick)的点击的实现都暴露出去。
3). getViewTypeCount() 1+每个Category中Adpater的ViewType。加1可以想象是每个Category都有一个标题。看代码运行的效果图应该能看出来,我们上面的效果图相当于有3个ViewType。
4). getItemViewType() 根据每个position去获取ViewType。
@Override
public int getItemViewType(int position) {
int typeOffset = 1;
for (Category category : categories) {
if (position == TITLE_POSITION) {
return VIEW_TYPE_TITLE;
}
int size = category.getAdapter().getCount() + 1;
if (position < size) {
return typeOffset + category.getAdapter().getItemViewType(position - 1);
}
position -= size;
typeOffset += category.getAdapter().getViewTypeCount();
}
return -1;
}
如果是标题的位置时候返回的是0类型,每个Catatory的ViewType则是慢慢的往上加的。这个应该好理解哦,for循环里面的逻辑应该也好理解就是判断当前的position是落在哪个Catogory上面或者是落在tittle上面的。仔细想下应该能想明白的。
5). getView()获取每个Item
public View getView(int position, View convertView, ViewGroup parent) {
int categoryIndex = 0;
for (Category category : categories) {
if (position == TITLE_POSITION) {
ViewHolder viewHolder = ViewHolder.getViewHolder(mContext, convertView, parent, mTitleLayoutId, position);
convertTitleView(viewHolder, categoryIndex);
return viewHolder.getConvertView();
}
int size = category.getAdapter().getCount() + 1;
if (position < size) {
return category.getAdapter().getView(position - 1, convertView, parent);
}
position -= size;
categoryIndex++;
}
return null;
}
for循环同样是判断position是落在哪个地方如果是title上面则用定义的布局文件,如果是落在具体的某个Category上面则是用Category中的Adapter对应的getView。
就写这一点点吧,写的很简单,具体的可以去参考下代码是怎么实现的,代码应该还算是比较简单的。
三. 源码下载
代码下载
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160599.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...