Android应用之——利用type为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没有很大区别。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值