實現(xiàn)了類似iOS的tableView功能梯影。不用事先創(chuàng)建好所有可能需要的控件巫员,再在運行時動態(tài)判斷顯示或隱藏。極大的提高了效率和減少了代碼量甲棍。
主要功能:
1.可對listView進行分組管理
2.每組都可以設置頭與尾
3.每組的多行可以定義多種布局文件
4.可加載多個布局文件简识,從而可定制頭與尾的布局文件
源碼請點擊github地址下載。IDE使用的是Eclipse感猛。
效果圖如下:
0C5CADD9B0F72C4A98C73866C4EABA34.png
API使用非常簡單七扰,與BaseAdapter的接口類似,按照例子的方法寫很容易實現(xiàn)陪白,demo有兩個界面颈走,從簡單實現(xiàn)到靈活運用。
只需要根據(jù)自己的業(yè)務創(chuàng)建一個Adapter繼承自LXBaseAdapter咱士,然后實現(xiàn)的方法查看LXBaseAdapterInterface接口選擇使用立由。
- 接口方法如下:
/**
* 點擊listView的觸發(fā)方法onItemClick里調(diào)用的接口,區(qū)別點擊的item序厉、頭或尾拆吆,與對應位置
**/
public interface LXOnListViewClick {
public void onItemClick(LXIndexPath idnexPath);
public void onHeaderClick(int section);
public void onfooterClick(int section);
}
/**
* 子類必須實現(xiàn)的方法
**/
//返回listview有幾組
public int getSectionInListView();
//返回第section組有幾個item行,不包括組頭與組尾
public int getCountInSection(int section);
//創(chuàng)建并返回在indexPath位置的item視圖(不要攝入頭尾)
public View getItemView(LXIndexPath indexPath, View convertView, ViewGroup parent);
/**
* 子類可選實現(xiàn)的方法
**/
/*
* 下面兩個方法若要實現(xiàn)必須成對實現(xiàn)/
*/
//定義第section組是否需要顯示頭脂矫。若返回TRUE枣耀,則必須實現(xiàn)下面getHeaderViewInSection方法。
public boolean showHeaderViewInSection(int section);
//創(chuàng)建并返回第section組的頭視圖
public View getHeaderViewInSection(int section, View convertView, ViewGroup parent);
/*
* 下面兩個方法若要實現(xiàn)必須成對實現(xiàn)/
*/
//定義第section組是否需要顯示尾庭再。若返回TRUE捞奕,則必須實現(xiàn)下面getFooterViewInSection方法。
public boolean showFooterViewInSection(int section);
//創(chuàng)建并返回第section組的尾視圖
public View getFooterViewInSection(int section, View convertView, ViewGroup parent);
/*
* item需要實現(xiàn)多種布局的接口/
*/
//返回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; //組位置颅围,(每一組可以包含多行)
}
- 監(jiān)聽方法:
在Activity里面監(jiān)聽了listView的點擊事件onItemClick方法,我們需要adapter調(diào)用getIndexPathWithPosition方法才會知道點擊的是item或頭或尾的對應位置恨搓,然后再處理相應的業(yè)務院促。代碼如下:
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的子元素是含有三個元素的數(shù)組筏养,第一個元素標記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() {
/*
* 設計思路:
*
* 統(tǒng)計返回的視圖的總個數(shù)弄抬。
* 將每組里面的所有行元素順序加起來就是position值茎辐。
* 如果有頭試圖或尾視圖,那么position將增加相應的值額外用來展現(xiàn)它們掂恕。 在此函數(shù)返回所有item個數(shù)與頭試圖和尾視圖的總和拖陆。
* 需要記錄在哪個position位置展現(xiàn)item或頭或尾,因此創(chuàng)建了一個三維數(shù)組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);
//根據(jù)子類定義的類型種類取得不同布局的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;
}
......
}