实现了类似iOS的tableView功能。不用事先创建好所有可能需要的控件,再在运行时动态判断显示或隐藏。极大的提高了效率和减少了代码量。
主要功能:
1.可对listView进行分组管理
2.每组都可以设置头与尾
3.每组的多行可以定义多种布局文件
4.可加载多个布局文件,从而可定制头与尾的布局文件
源码请点击github地址下载。IDE使用的是Eclipse。
效果图如下:
API使用非常简单,与BaseAdapter的接口类似,按照例子的方法写很容易实现,demo有两个界面,从简单实现到灵活运用。
只需要根据自己的业务创建一个Adapter继承自LXBaseAdapter,然后实现的方法查看LXBaseAdapterInterface接口选择使用。
- 接口方法如下:
/**
* 点击listView的触发方法onItemClick里调用的接口,区别点击的item、头或尾,与对应位置
**/
public interface LXOnListViewClick {
public void onItemClick(LXIndexPath idnexPath);
public void onHeaderClick(int section);
public void onfooterClick(int section);
}
/**
* 子类必须实现的方法
**/
//返回listview有几组
public int getSectionInListView();
//返回第section组有几个item行,不包括组头与组尾
public int getCountInSection(int section);
//创建并返回在indexPath位置的item视图(不要摄入头尾)
public View getItemView(LXIndexPath indexPath, View convertView, ViewGroup parent);
/**
* 子类可选实现的方法
**/
/*
* 下面两个方法若要实现必须成对实现/
*/
//定义第section组是否需要显示头。若返回TRUE,则必须实现下面getHeaderViewInSection方法。
public boolean showHeaderViewInSection(int section);
//创建并返回第section组的头视图
public View getHeaderViewInSection(int section, View convertView, ViewGroup parent);
/*
* 下面两个方法若要实现必须成对实现/
*/
//定义第section组是否需要显示尾。若返回TRUE,则必须实现下面getFooterViewInSection方法。
public boolean showFooterViewInSection(int section);
//创建并返回第section组的尾视图
public View getFooterViewInSection(int section, View convertView, ViewGroup parent);
/*
* item需要实现多种布局的接口/
*/
//返回indexPath位置的item类型
public int getOnlyItemViewType(LXIndexPath indexPath);
//返回item一共有几种类型(不包含头与尾)
public int getOnlyItemViewTypeCountSum();
/**
* 子类不能复写的接口
* */
//用于item被点击时传入position取到对应的indexPath(当row==-1代表为头视图,row==-2代表为尾视图)
public LXIndexPath getIndexPathWithPosition(int position, LXOnListViewClick listener);
- 记录位置的model
public class LXIndexPath {
public int row; //行位置
public int section; //组位置,(每一组可以包含多行)
}
- 监听方法:
在Activity里面监听了listView的点击事件onItemClick方法,我们需要adapter调用getIndexPathWithPosition方法才会知道点击的是item或头或尾的对应位置,然后再处理相应的业务。代码如下:
adapter.getIndexPathWithPosition(position, new LXOnListViewClick() {
@Override
public void onItemClick(LXIndexPath indexPath) {
Log.e("onItemClick", "indexPath:" + indexPath.section+":"+indexPath.row);
}
@Override
public void onHeaderClick(int section) {
Log.e("onHeaderClick", "section:"+section);
}
@Override
public void onfooterClick(int section) {
Log.e("onfooterClick", "section:"+section);
}
});
- 核心代码:
public abstract class LXBaseAdapter extends BaseAdapter implements
LXBaseAdapterInterface {
private LXBaseAdapter subClass;
// recodeIndexs的子元素是含有三个元素的数组,第一个元素标记position,第二个元素>0表示为item视图,TYPE_HEADER表示为头,为TYPE_FOOTER表示尾。
private List<int[]> recodeIndexs = new ArrayList<int[]>();
private final int TYPE_HEADER = -1;
private final int TYPE_FOOTER = -2;
@Override
public int getCount() {
/*
* 设计思路:
*
* 统计返回的视图的总个数。
* 将每组里面的所有行元素顺序加起来就是position值。
* 如果有头试图或尾视图,那么position将增加相应的值额外用来展现它们。 在此函数返回所有item个数与头试图和尾视图的总和。
* 需要记录在哪个position位置展现item或头或尾,因此创建了一个三维数组recodeIndex[][]用于记录。
* recodeIndex[][0]代表特殊位置的position。
* recodeIndex[][1]代表(item、头或尾)视图所在的组位置
* recodeIndex[][2]>0表示为item视图,TYPE_HEADER表示为头,为TYPE_FOOTER表示尾。
*
* */
int section = subClass.getSectionInListView();
int count = 0;
recodeIndexs.clear();
for (int i = 0; i < section; i++) {
//判断有无组头,若有则记录位置与类型
if (getHeaderBool(i) == 1) {
int[] headerIndex = new int[3];
headerIndex[0] = count;
headerIndex[1] = TYPE_HEADER;
headerIndex[2] = i;
count++;
recodeIndexs.add(headerIndex);
}
//记录组的行成员
for (int j = 0; j < subClass.getCountInSection(i); j++) {
int[] index = new int[3];
index[0] = count+j;
index[1] = j;
index[2] = i;
recodeIndexs.add(index);
}
count += subClass.getCountInSection(i);
//判断有无组尾,若有则记录位置与类型
if (getfooterBool(i) == 1) {
int[] footerIndex = new int[3];
footerIndex[0] = count;
footerIndex[1] = TYPE_FOOTER;
footerIndex[2] = i;
recodeIndexs.add(footerIndex);
count++;
}
}
for (int i = 0; i < recodeIndexs.size(); i++) {
Log.e("recodeIndex", recodeIndexs.get(i)[0] + "."+recodeIndexs.get(i)[1] + "."+recodeIndexs.get(i)[2]);
}
return count;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
switch (getItemViewType(position)) {
case TYPE_HEADER:
return subClass.getHeaderViewInSection(recodeIndexs.get(position)[2],
convertView, parent);
case TYPE_FOOTER:
return subClass.getFooterViewInSection(recodeIndexs.get(position)[2],
convertView, parent);
//根据子类定义的类型种类取得不同布局的item
default:
LXIndexPath itemIndexPath = new LXIndexPath();
itemIndexPath.row = recodeIndexs.get(position)[1];
itemIndexPath.section = recodeIndexs.get(position)[2];
return subClass.getItemView(itemIndexPath, convertView, parent);
}
}
@Override
public int getViewTypeCount() {
int itemTypeCount = subClass.getOnlyItemViewTypeCountSum();
return 2 + (itemTypeCount > 0 ? itemTypeCount : 1);
}
@Override
public int getItemViewType(int position) {
LXIndexPath itemIndexPath = new LXIndexPath();
itemIndexPath.row = recodeIndexs.get(position)[1];
itemIndexPath.section = recodeIndexs.get(position)[2];
int type = subClass.getOnlyItemViewType(itemIndexPath);
if (type > 0) {
//代表item有多种布局
return type;
}
if (itemIndexPath.row >= 0) {
//代表item只有一种布局
return 0;
}
//代表返回头或尾的布局
return itemIndexPath.row;
}
......
}