0%

Android ListView分类/分组效果

虽然现在有了ExpandableListView可以代替ListView进行分组显示,但是不能在显示分组的同时显示无分组数据,做不到更高级的自定义,所以我在网上找了这篇文章,以后可以用得上。以下所有ListView均可替换为RecyclerView进行重新实现。

实现ListView分类显示效果,目前我知道的有两种方案:

  1. 每一个ItemView都包含用于显示分类信息的view(TitleView)和用于显示内容view(参考带索引的listview)
  2. 通过ListView加载不同类型的Item实现。本文属于这种实现方式

当前实现描述:

与自定义Adapter的ListVIew雷同,只是多使用两个BaseAdapter API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int getItemViewType (int position)  

获取通过getView为指定项目创建的视图的类型。
参数
position 在adapter数据里我们想知道视图类型的项目的位置
返回值
一个整形的视图类型的描述。如果一个视图通过getView(int, View, ViewGroup)方法转换成另一个视图,则两个视图将共享同一类型。注意:整形必须在0和getViewTypeCount()– 1之间。IGNORE_ITEM_VIEW_TYPE也可以返回。


public int getViewTypeCount ()

返回通过getView(int, View, ViewGroup))创建的视图的类型数量。每一个类型表示一组通过getView(int, View, ViewGroup)方法转换过的视图。如果adapter针对所有项目返回相同的视图类型,这个方法返回1。这个方法仅仅当adapter设置在AdapterView时调用。

返回值
通过这个adapter创建的视图类型的数量

视图 – 在Adapter.getView中通过getItemViewType获取item类型,当前实现为分类item与普通item两种,根据类型创建不同的VIew对象
数据 – 分类的数据通过List包含自定义数据对象Category,Category内部包含List用于存储当前Category item数据。
覆写BaseAdapter.areAllItemsEnabled 和 BaseAdapter.isEnabled两个方法,确保分类Item不可点击

代码:

Activity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class MainActivity extends Activity {  

private CategoryAdapter mCustomBaseAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ListView listView = (ListView) findViewById(R.id.listView1);

// 数据
ArrayList<Category> listData = getData();

mCustomBaseAdapter = new CategoryAdapter(getBaseContext(), listData);

// 适配器与ListView绑定
listView.setAdapter(mCustomBaseAdapter);

listView.setOnItemClickListener(new ItemClickListener());
}


private class ItemClickListener implements OnItemClickListener {

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(getBaseContext(), (String)mCustomBaseAdapter.getItem(position),
Toast.LENGTH_SHORT).show();
}

}


/**
* 创建测试数据
*/
private ArrayList<Category> getData() {
ArrayList<Category> listData = new ArrayList<Category>();
Category categoryOne = new Category("路人甲");
categoryOne.addItem("马三立");
categoryOne.addItem("赵本山");
categoryOne.addItem("郭德纲");
categoryOne.addItem("周立波");
Category categoryTwo = new Category("事件乙");
categoryTwo.addItem("**贪污");
categoryTwo.addItem("**照门");
Category categoryThree = new Category("书籍丙");
categoryThree.addItem("10天学会***");
categoryThree.addItem("**大全");
categoryThree.addItem("**秘籍");
categoryThree.addItem("**宝典");
categoryThree.addItem("10天学会***");
categoryThree.addItem("10天学会***");
categoryThree.addItem("10天学会***");
categoryThree.addItem("10天学会***");
Category categoryFour = new Category("书籍丙");
categoryFour.addItem("河南");
categoryFour.addItem("天津");
categoryFour.addItem("北京");
categoryFour.addItem("上海");
categoryFour.addItem("广州");
categoryFour.addItem("湖北");
categoryFour.addItem("重庆");
categoryFour.addItem("山东");
categoryFour.addItem("陕西");

listData.add(categoryOne);
listData.add(categoryTwo);
listData.add(categoryThree);
listData.add(categoryFour);

return listData;
}
}
Adapter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
public class CategoryAdapter extends BaseAdapter {  

private static final int TYPE_CATEGORY_ITEM = 0;
private static final int TYPE_ITEM = 1;

private ArrayList<Category> mListData;
private LayoutInflater mInflater;


public CategoryAdapter(Context context, ArrayList<Category> pData) {
mListData = pData;
mInflater = LayoutInflater.from(context);
}

@Override
public int getCount() {
int count = 0;

if (null != mListData) {
// 所有分类中item的总和是ListVIew Item的总个数
for (Category category : mListData) {
count += category.getItemCount();
}
}

return count;
}

@Override
public Object getItem(int position) {

// 异常情况处理
if (null == mListData || position < 0|| position > getCount()) {
return null;
}

// 同一分类内,第一个元素的索引值
int categroyFirstIndex = 0;

for (Category category : mListData) {
int size = category.getItemCount();
// 在当前分类中的索引值
int categoryIndex = position - categroyFirstIndex;
// item在当前分类内
if (categoryIndex < size) {
return category.getItem( categoryIndex );
}

// 索引移动到当前分类结尾,即下一个分类第一个元素索引
categroyFirstIndex += size;
}

return null;
}

@Override
public int getItemViewType(int position) {
// 异常情况处理
if (null == mListData || position < 0|| position > getCount()) {
return TYPE_ITEM;
}


int categroyFirstIndex = 0;

for (Category category : mListData) {
int size = category.getItemCount();
// 在当前分类中的索引值
int categoryIndex = position - categroyFirstIndex;
if (categoryIndex == 0) {
return TYPE_CATEGORY_ITEM;
}

categroyFirstIndex += size;
}

return TYPE_ITEM;
}

@Override
public int getViewTypeCount() {
return 2;
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

int itemViewType = getItemViewType(position);
switch (itemViewType) {
case TYPE_CATEGORY_ITEM:
if (null == convertView) {
convertView = mInflater.inflate(R.layout.listview_item_header, null);
}

TextView textView = (TextView) convertView.findViewById(R.id.header);
String itemValue = (String) getItem(position);
textView.setText( itemValue );
break;

case TYPE_ITEM:
ViewHolder viewHolder = null;
if (null == convertView) {

convertView = mInflater.inflate(R.layout.listview_item, null);

viewHolder = new ViewHolder();
viewHolder.content = (TextView) convertView.findViewById(R.id.content);
viewHolder.contentIcon = (ImageView) convertView.findViewById(R.id.content_icon);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}

// 绑定数据
viewHolder.content.setText( (String)getItem(position) );
viewHolder.contentIcon.setImageResource(R.drawable.ic_launcher);
break;
}

return convertView;
}


@Override
public boolean areAllItemsEnabled() {
return false;
}

@Override
public boolean isEnabled(int position) {
return getItemViewType(position) != TYPE_CATEGORY_ITEM;
}


private class ViewHolder {
TextView content;
ImageView contentIcon;
}

}
数据对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Category {  

private String mCategoryName;
private List<String> mCategoryItem = new ArrayList<String>();

public Category(String mCategroyName) {
mCategoryName = mCategroyName;
}

public String getmCategoryName() {
return mCategoryName;
}

public void addItem(String pItemName) {
mCategoryItem.add(pItemName);
}

/**
* 获取Item内容
*
* @param pPosition
* @return
*/
public String getItem(int pPosition) {
// Category排在第一位
if (pPosition == 0) {
return mCategoryName;
} else {
return mCategoryItem.get(pPosition - 1);
}
}

/**
* 当前类别Item总数。Category也需要占用一个Item
* @return
*/
public int getItemCount() {
return mCategoryItem.size() + 1;
}

}