【声明】此文出自指尖飞落的博客:http://blog.youkuaiyun.com/huntersnail
——每天写一篇博客,每天做一点技术积累!
最近在项目版本迭代中需要用到分类的ListView,小区下面的N条收货地址(类似联系人)。以前都是用的很普通的ListView,都写熟透了,这种倒是没写过,就研究了下。如果是联系人那种简单的布局到也好解决,标题和子Item都可以用一个Xml布局解决。主要的难点是此次的需求是标题和子Item布局不一样,子Item还有很多点击事件需要处理,删除、编辑、选中等,有三个入口,还要根据不同的入口进行布局相应的显示。下面来说说:
思路:1、首先创建自定义适配器
2、创建一个中间实体,用来连接Head和Body
3、最后,在Activity里进行区分Head和Body的逻辑处理与数据装载
先贴一下项目中需要实现的效果图:
1、自定义的适配器
package com.ed.categorylistview;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class CategoryAdapter extends BaseAdapter {
private LayoutInflater inflater;
private Context context;
private List<CategoryItem> categoryItems;
public CategoryAdapter(Context context, List<CategoryItem> categoryItems) {
this.context = context;
inflater = LayoutInflater.from(context);
this.categoryItems = categoryItems;
}
@Override
public int getCount() {
return categoryItems.size();
}
@Override
public Object getItem(int position) {
return categoryItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
/**
* 获得视图的类型
*/
@Override
public int getItemViewType(int position) {
return ((CategoryItem) getItem(position)).type;
}
/**
* 获得视图的类型数量
*/
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
// 获得视图类型
int type = getItemViewType(position);
// 获得每一条CategoryItem
CategoryItem item = (CategoryItem) getItem(position);
switch (type) {
case CategoryItem.TITLE:// Head
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_address_title,
null);
}
TextView mTitle = (TextView) convertView
.findViewById(R.id.tv_address_title);
// 设置Head
mTitle.setText(item.getSection());
break;
case CategoryItem.ITEM:// Body
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.item_address_content,
null);
viewHolder.mName = (TextView) convertView
.findViewById(R.id.tv_consignee_name);
viewHolder.mPhone = (TextView) convertView
.findViewById(R.id.tv_consignee_phone);
viewHolder.mAddress = (TextView) convertView
.findViewById(R.id.tv_consignee_address);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 获得每一条地址信息
AddressItem address = (AddressItem) item.getItem();
// 进行赋值
viewHolder.mName.setText(address.getName());
viewHolder.mPhone.setText(address.getPhone());
viewHolder.mAddress.setText(address.getAddress());
break;
}
return convertView;
}
/**
* @ClassName ViewHolder
* @author Endoon
*/
static class ViewHolder {
TextView mName;
TextView mPhone;
TextView mAddress;
}
}
2、创建一个中间实体,用来连接Head和Body
package com.ed.categorylistview;
public class CategoryEntity {
public static final int TITLE=0;
public static final int ITEM=1;
public Object item;
public int type;
public String section;
public CategoryEntity(Object item,int type,String section) {
this.item=item;
this.type=type;
this.section=section;
}
public Object getItem() {
return item;
}
public void setItem(Object item) {
this.item = item;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
}
package com.ed.categorylistview;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ListView;
/**
* @Description 主页
* @author Endoon
* @date 2015-11-2 14:13:17
*/
public class MainActivity extends Activity {
private ListView mListView;
private CategoryAdapter mAdapter;
private List<CategoryEntity> categoryItems = new ArrayList<CategoryEntity>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.lv_content);
initView();
}
/**
* 初始化视图
*/
private void initView() {
initCategoryItems(simulateData());
mAdapter = new CategoryAdapter(MainActivity.this, categoryItems);
mListView.setAdapter(mAdapter);
}
/**
* 区分Head(头)和Body(体)的逻辑处理:此方法非常关键
* @param simulateData 模拟的数据源
*/
private void initCategoryItems(List<Address> simulateData) {
categoryItems.clear();
for (int i = 0; i < simulateData.size(); i++) {
Address address = simulateData.get(i);
// 当前的Head
String currentTitle = address.getTitle();
// 判断上一个Head:判断是否有上一个Head,如有有则用上一个Head,如果没有则用空表示;
String lastTitle = (i - 1) >= 0 ? (simulateData.get(i - 1).getTitle()) : " ";
/**
* 通过对当前Head与上一个Head进行对比,如果不是同一个头,则添加进行存储
*/
if (!currentTitle.equals(lastTitle)) {
CategoryEntity firstItem=new CategoryEntity(null, CategoryEntity.TITLE, currentTitle);
categoryItems.add(firstItem);
}
/**
* 循环添加Head下面Body,添加完当前Head的Body则会进行下一轮的Head对比,不相等则再进行新的一轮的Body的添加。以此类推
*/
List<AddressItem> items=address.getItems();
for (AddressItem addressItem : items) {
CategoryEntity item=new CategoryEntity(addressItem, CategoryEntity.ITEM, currentTitle);
categoryItems.add(item);
}
}
}
/**
* 模拟数据源
* @return 数据源
*/
private List<Address> simulateData() {
List<Address> list = new ArrayList<Address>();
for (int i = 0; i < 3; i++) {
Address address = new Address();
address.setTitle("碧桂园威尼斯城" + i + 1 + "期");
List<AddressItem> listAdrs = new ArrayList<AddressItem>();
for (int j = 0; j < 3; j++) {
AddressItem item = new AddressItem();
item.setName("老王" + j);
item.setPhone("1551111111" + j);
item.setAddress("北京市朝阳区长安街第" + j + "号");
listAdrs.add(item);
}
address.setItems(listAdrs);
list.add(address);
}
return list;
}
}
4、Demo实现的效果图
5、源码下载地址
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆转载请注明出处☞指尖飞落的博客☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆