Android应用之——利用getItemViewType为Listview的item设置不同的布局

一、概述

在项目的需求中,有一处需要显示一个交易记录的列表,这个列表很容易让人联想到用listview来实现,但是这个列表又有稍许不同的地方,那就是它里面的item并不是一样的布局,其中某些部分显示的是消费的记录,而有些地方显示的是充值的记录,也就对应了不同的item布局。而且,这两处地方都是从服务端获取数据的,这两个item的数据对应的类内容也各不相同,该怎么处理呢?

下面来一步步实现这个效果。

二、先看效果图

三、实现步骤

实现的原理就是listview的adapter中的一个关键的方法就是getItemViewType(getItemViewType),这个方法有一个参数是position,有了这个position我们就可以对list集合中的不同位置的数据进行不同的处理,进而标识不同的type,将list中的数据进行分类处理。

首先进行,数据的准备:

在这个项目中,数据源是从服务端获取的json数据,数据的格式如下:

{
    "status_code": "0",
    "result": [
        {
            "mr_content": {
                "point": "10",
                "member_money": "100",
                "pay_money": "300",
                "cash": "200",
                "bonus": "消费满200元立减50元餐券1张",
                "activities": "三锅鸡1元任吃",
                "coupon": "满100送50",
                "branch_name": "四海一家"
            },
            "mr_id": "25",
            "mr_createtime": "1333333333",
            "mr_type": "0",
            "user_id": "108",
            "merchant_id": "1",
            "branch_id": "1",
            "branch_name": "ffff"
        },
        {
            "mr_content": {
                "member_money": "300",
                "branch_name": "四海一家"
            },
            "mr_id": "30",
            "mr_createtime": "1333333333",
            "mr_type": "1",
            "user_id": "108",
            "merchant_id": "1",
            "branch_id": "1",
            "branch_name": "fff"
        }
    ],
    "status_desc": "ok"
}

可以看到其中mr_content这个字段,是一个自定义对象,但是两个mr_content的内容不同,这里是分别为mr_content的内容定义两个不同的类还是如何处理呢?

一开始,我是分别为两个mr_content定义不同的类,后来发现这样行不通,因为这样做的话定义外层类的时候mr_content就无法指定数据类型了。所以,最后采用某人的方法将mr_content定义为一个类,将两个不同的mr_content的字段都定义进去,解析的时候不会出现问题,没有数据会显示null

下面是我定义的mr_content字段的数据类型ComsumAndChargeRecordBean

public class ComsumAndChargeRecordBean {
	private String branch_name;
	private String pay_money;
	private String coupon;//使用特权
	private String activities;
	private String member_money;
	private String cash;
	private String point;
	private String bonus;
//	private String prestore_money;//预存款

	public String getBranch_name() {
		return branch_name;
	}
	public void setBranch_name(String branch_name) {
		this.branch_name = branch_name;
	}
	public String getPay_money() {
		return pay_money;
	}
	public void setPay_money(String pay_money) {
		this.pay_money = pay_money;
	}
	public String getCoupon() {
		return coupon;
	}
	public void setCoupon(String coupon) {
		this.coupon = coupon;
	}
	public String getActivities() {
		return activities;
	}
	public void setActivities(String activities) {
		this.activities = activities;
	}
	public String getMember_money() {
		return member_money;
	}
	public void setMember_money(String member_money) {
		this.member_money = member_money;
	}
	public String getCash() {
		return cash;
	}
	public void setCash(String cash) {
		this.cash = cash;
	}
	public String getPoint() {
		return point;
	}
	public void setPoint(String point) {
		this.point = point;
	}
	public String getBonus() {
		return bonus;
	}
	public void setBonus(String bonus) {
		this.bonus = bonus;
	}
}

数据准备好了,下面是传入listview中进行显示:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include
        android:id="@+id/traderecord_layout"
        layout="@layout/topview_activity" />

    <ListView
        android:id="@+id/lv_my_traderecord"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</LinearLayout>

两个不同item的布局文件就省略了,相信大家都会,这个没什么难度

下面是主界面代码:

<pre class="java" name="code">	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_trade_record);

		mListView = (ListView) findViewById(R.id.lv_my_traderecord);
		E_TempTradeRecordAdapter adapter = new E_TempTradeRecordAdapter(
				E_TradeRecordActivity.this, myModel.tradeRecordList);
		mListView.setAdapter(adapter);
		adapter.notifyDataSetChanged();
	}

下面是adapter适配器的一部分代码:

字段和构造函数:

private static final String TAG = "E_TradeRecordAdapter";
	private static final int TYPE_COUNT = 2;//item类型的总数
	private static final int TYPE_COMSUM = 0;//消费类型
	private static final int TYPE_CHARGE = 1;//充值类型
	private ArrayList<TradeRecordBean> dataList = new ArrayList<TradeRecordBean>();//数据集合
	private Context mContext;
	private int currentType;//当前item类型

	public E_TempTradeRecordAdapter(Context mContext,
			ArrayList<TradeRecordBean> dataList) {
		super();
		this.dataList = dataList;
		this.mContext = mContext;
	}

几个重要方法:

@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return dataList.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return dataList.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

获取子item的类型 获取类型的数量  这里是根据字段Mr_type来确定的,json数据里面是根据这个字段来确定消费记录的类型的。总之,在为item设置不同的布局的时候肯定有一个标记用来区分不同的item,你可以用这个作为判断的标记,来设置不同的type。

@Override
	public int getItemViewType(int position) {
		// TODO Auto-generated method stub
		if ("0".equals(dataList.get(position).getMr_type())) {
			return TYPE_COMSUM;// 消费类型
		} else if ("1".equals(dataList.get(position).getMr_type())) {
			return TYPE_CHARGE;// 充值类型
		} else {
			return 100;
		}
	}

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

viewholder:缓存这几个textview控件

/**
	 * 消费记录
	 * @author yl
	 *
	 */
	class ComsumViewHolder {
		TextView branchnameCom;
		TextView comsumemoney;
		TextView useprevillage;
		TextView yuezhifu;
		TextView cash;
		TextView thisscore;
		TextView extrareward;
		TextView prestoremoney;
	}

	/**
	 * 充值记录
	 * @author yl
	 *
	 */
	class ChargeViewHolder {
		TextView branchnameCha;
		TextView prestoremoney;
		TextView extrasmoney;
		TextView totalmoney;
	}

最后是getview方法:其中有一个关键的方法

currentType = getItemViewType(position);

这个方法获取到当前position的类型,也就是在前面的getItemViewType方法设置的类型。

其中对convertView进行了复用和holder的使用,算是对listview的优化吧。

当currentType == TYPE_COMSUM,消费类型时,加载comsumView = LayoutInflater.from(mContext).inflate(  R.layout.traderecord_item_comsume, null);消费类型的布局文件。反之,加载充值类型的布局文件。这样就可以达到为不同的item设置不同的布局文件了。

	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		View comsumView = null;
		View chargeView = null;

		ComsumAndChargeRecordBean record = (ComsumAndChargeRecordBean) dataList
				.get(position).getMr_content();

		currentType = getItemViewType(position);
		if (currentType == TYPE_COMSUM) {
			ComsumViewHolder comsumHolder = null;
			if (convertView == null) {
				comsumHolder = new ComsumViewHolder();
				comsumView = LayoutInflater.from(mContext).inflate(
						R.layout.traderecord_item_comsume, null);
				comsumHolder.branchnameCom = (TextView) comsumView
						.findViewById(R.id.tv_branch_name);
				comsumHolder.comsumemoney = (TextView) comsumView
						.findViewById(R.id.tv_comsumemoney);
				comsumHolder.useprevillage = (TextView) comsumView
						.findViewById(R.id.tv_useprevillage);
				comsumHolder.yuezhifu = (TextView) comsumView
						.findViewById(R.id.tv_yuezhifu);
				comsumHolder.cash = (TextView) comsumView
						.findViewById(R.id.tv_cash);
				comsumHolder.thisscore = (TextView) comsumView
						.findViewById(R.id.tv_thisscore);
				comsumHolder.extrareward = (TextView) comsumView
						.findViewById(R.id.tv_extrareward);
				comsumView.setTag(comsumHolder);
				convertView = comsumView;
			} else {
				comsumHolder = (ComsumViewHolder) convertView.getTag();
			}
			comsumHolder.branchnameCom.setText(DateFormatUtil.formatDate(Long
					.valueOf(dataList.get(position).getMr_createtime()))
					+ "  "
					+ record.getBranch_name());// 消费时间和分店
			comsumHolder.comsumemoney.setText(record.getPay_money());// 消费金额
			comsumHolder.useprevillage.setText(record.getCoupon());// 使用特权
			comsumHolder.yuezhifu.setText(record.getMember_money());// 余额支付
			comsumHolder.cash.setText(record.getCash());// 现金支付
			comsumHolder.thisscore.setText(record.getPoint());// 本次积分
			comsumHolder.extrareward.setText(record.getBonus());// 额外奖励
		} else if (currentType == TYPE_CHARGE) {
			ChargeViewHolder chargeHoler = null;
			if (convertView == null) {
				chargeHoler = new ChargeViewHolder();
				chargeView = LayoutInflater.from(mContext).inflate(
						R.layout.traderecord_item_chongzhi, null);
				chargeHoler.branchnameCha = (TextView) chargeView
						.findViewById(R.id.tv_branchname_charge);
				chargeHoler.prestoremoney = (TextView) chargeView
						.findViewById(R.id.tv_prestoremoney);
				chargeHoler.extrasmoney = (TextView) chargeView
						.findViewById(R.id.tv_extrasmoney);
				chargeHoler.totalmoney = (TextView) chargeView
						.findViewById(R.id.tv_totalmoney);
				chargeView.setTag(chargeHoler);
				convertView = chargeView;
			} else {
				chargeHoler = (ChargeViewHolder) convertView.getTag();
			}

			chargeHoler.branchnameCha.setText(DateFormatUtil.formatDate(Long
					.valueOf(dataList.get(position).getMr_createtime()))
					+ " "
					+ record.getBranch_name());// 消费时间和分店
			// chargeHoler.prestoremoney.setText(record.getPrestore_money() +
			// "元");// 存款
			chargeHoler.extrasmoney.setText(record.getMember_money() + "元");// 余额
			chargeHoler.totalmoney.setText(record.getMember_money() + "元");// 合计
		}
		return convertView;
	}

上面就是整个效果的实现过程

四、总结

其实为listview的item设置不同的布局文件,达到上面的效果,步骤如下;

1、为不同的item写不同的布局文件,设置统一的javabean类

2、继承BaseAdapter类,实现getItemViewType(int position)和getViewTypeCount() 方法,根据这两个方法,为item设置不同的标记,也就是不同的type

3、在getView方法中,利用getItemViewType(position)方法获取当前的type类型,然后根据不同的type类型,加载不同的item布局文件。

4、其他的一些listview的优化同一般的listview没有很大区别。



Android应用之——利用getItemViewType为Listview的item设置不同的布局

时间: 2024-10-11 16:20:32

Android应用之——利用getItemViewType为Listview的item设置不同的布局的相关文章

Android BaseAdapter和ViewHolder 优化 解决ListView的item抢焦点问题和item错乱问题

首先赞下hyman大神 曾经仅仅是简单的重写个BaseAdapter,将getView方法保持抽象.而ViewHolder没有抽象过. .. ViewHolder (用了一个集合+泛型管理存取view) /** * author : stone * email : [email protected] * time : 15/7/24 14 27 */ public class StoneViewHolder { private int mPosition; private View mConve

Android SwipeToDismiss:左滑/右滑删除ListView条目Item

?? <Android SwipeToDismiss:左右滑动删除ListView条目Item> Android的SwipeToDismiss是github上一个第三方开源框架(github上的项目链接地址:https://github.com/romannurik/Android-SwipeToDismiss ).该开源项目旨在:使得一个ListView的item在用户的手指在屏幕上左滑或者右滑时候,删除当前的这个ListView Item. 此种特效在新版的Android中应用不少.比方在

Android小白的成长之路-ListView优化提案

在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能. 本文的重点即是从如下几个方面介绍如何对ListView进行优化. 1.convertView重用 利用好 convertView 来重用 View,切忌每次 getView() 都新建.ListView 的核心原理就是重用 View,如果重用 view 不改变宽高,重用V

【转】Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果

原文网址:http://blog.csdn.net/xiaanming/article/details/17539199 我在上一篇文章中Android 带你从源码的角度解析Scroller的滚动实现原理从源码的角度介绍了Scroller的滚动实现原理,相信大家对Scroller的使用有一定的了解,这篇文章就给大家带来使用Scroller的小例子,来帮助大家更加熟悉的掌握Scroller的使用,掌握好了Scroller的使用我们就能实现很多滑动的效果.例如侧滑菜单,launcher,ListVi

android学习笔记——利用BaseAdapter生成40个列表项

RT: main.xml ? 1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"               android:orientation="vertical"        

本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877)Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很棒,当我们滑动Item超过一半的时候,item的透明度就变成了0,我们就知道抬起手指的时候item就被删除了,当item的透明度不为0的时候,我们抬起手指Item会回到起始位置,这样我们就知道

Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果, 之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很棒,当我们滑动Item超过一半的时候,item的透明度就变 成了0,我们就知道抬起手指的时候item就被删除了,当item的透明度不为0的时候,我们抬起手指Item会回到起始位置,这样我们就

Android学习---ListView和Inflater的使用,将一个布局文件转化为一个对象

本文将介绍ListView和Inflater的使用,将接上一篇文章内容. 一.什么是ListView? 在android开发中ListView是比较常用的控件,ListView 控件可使用四种不同视图显示项目,1.大(标准)图标2.小图标3.列表4.报表,比较常用的是列表的形式.ListItem 对象可包含文本和图片.然而,若要使用图片则必须通过 Icons 和 SmallIcons 属性引用 ImageList控件. 本文将接着上一篇文章,将sqlite数据库的数据以列表的形式显示出来. 二.

Android之史上最强ListView优化方案

在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能. 本文的重点即是从如下几个方面介绍如何对ListView进行优化. 1.convertView重用 Android SDK中这样讲: the old view to reuse, if possible. Note: You should check that this v