Android的分类ListView

【声明】此文出自指尖飞落的博客:http://blog.csdn.net/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;
	}
}


3、在Activity里进行区分Head和Body的逻辑处理与数据装载

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、源码下载地址


☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆转载请注明出处☞指尖飞落的博客☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值