Andriod之Adapter的getViewTypeCount和getItemViewType为Listview的item设置不同的布局

一、概述

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

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

二、先看效果图

\

三、实现步骤

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

首先进行,数据的准备:

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

01. {
02. "status_code""0",
03. "result": [
04. {
05. "mr_content": {
06. "point""10",
07. "member_money""100",
08. "pay_money""300",
09. "cash""200",
10. "bonus""消费满200元立减50元餐券1张",
11. "activities""三锅鸡1元任吃",
12. "coupon""满100送50",
13. "branch_name""四海一家"
14. },
15. "mr_id""25",
16. "mr_createtime""1333333333",
17. "mr_type""0",
18. "user_id""108",
19. "merchant_id""1",
20. "branch_id""1",
21. "branch_name""ffff"
22. },
23. {
24. "mr_content": {
25. "member_money""300",
26. "branch_name""四海一家"
27. },
28. "mr_id""30",
29. "mr_createtime""1333333333",
30. "mr_type""1",
31. "user_id""108",
32. "merchant_id""1",
33. "branch_id""1",
34. "branch_name""fff"
35. }
36. ],
37. "status_desc""ok"
38. }

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

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

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

01. public class ComsumAndChargeRecordBean {
02. private String branch_name;
03. private String pay_money;
04. private String coupon;//使用特权
05. private String activities;
06. private String member_money;
07. private String cash;
08. private String point;
09. private String bonus;
10. //  private String prestore_money;//预存款
11.  
12. public String getBranch_name() {
13. return branch_name;
14. }
15. public void setBranch_name(String branch_name) {
16. this.branch_name = branch_name;
17. }
18. public String getPay_money() {
19. return pay_money;
20. }
21. public void setPay_money(String pay_money) {
22. this.pay_money = pay_money;
23. }
24. public String getCoupon() {
25. return coupon;
26. }
27. public void setCoupon(String coupon) {
28. this.coupon = coupon;
29. }
30. public String getActivities() {
31. return activities;
32. }
33. public void setActivities(String activities) {
34. this.activities = activities;
35. }
36. public String getMember_money() {
37. return member_money;
38. }
39. public void setMember_money(String member_money) {
40. this.member_money = member_money;
41. }
42. public String getCash() {
43. return cash;
44. }
45. public void setCash(String cash) {
46. this.cash = cash;
47. }
48. public String getPoint() {
49. return point;
50. }
51. public void setPoint(String point) {
52. this.point = point;
53. }
54. public String getBonus() {
55. return bonus;
56. }
57. public void setBonus(String bonus) {
58. this.bonus = bonus;
59. }
60. }


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

布局文件:

01. <?xml version="1.0" encoding="utf-8"?>
02. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03. android:layout_width="match_parent"
04. android:layout_height="match_parent"
05. android:orientation="vertical" >
06.  
07. <include
08. android:id="@+id/traderecord_layout"
09. layout="@layout/topview_activity" />
10.  
11. <ListView
12. android:id="@+id/lv_my_traderecord"
13. android:layout_width="match_parent"
14. android:layout_height="match_parent" >
15. </ListView>
16.  
17. </LinearLayout>

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

下面是主界面代码:

01. <pre class="java" name="code">    protected void onCreate(Bundle savedInstanceState) {
02. // TODO Auto-generated method stub
03. super.onCreate(savedInstanceState);
04. setContentView(R.layout.activity_trade_record);
05.  
06. mListView = (ListView) findViewById(R.id.lv_my_traderecord);
07. E_TempTradeRecordAdapter adapter = new E_TempTradeRecordAdapter(
08. E_TradeRecordActivity.this, myModel.tradeRecordList);
09. mListView.setAdapter(adapter);
10. adapter.notifyDataSetChanged();
11. }

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

字段和构造函数:

01. private static final String TAG = "E_TradeRecordAdapter";
02. private static final int TYPE_COUNT = 2;//item类型的总数
03. private static final int TYPE_COMSUM = 0;//消费类型
04. private static final int TYPE_CHARGE = 1;//充值类型
05. private ArrayList<TradeRecordBean> dataList = new ArrayList<TradeRecordBean>();//数据集合
06. private Context mContext;
07. private int currentType;//当前item类型
08.  
09. public E_TempTradeRecordAdapter(Context mContext,
10. ArrayList<TradeRecordBean> dataList) {
11. super();
12. this.dataList = dataList;
13. this.mContext = mContext;
14. }

几个重要方法:

01. @Override
02. public int getCount() {
03. // TODO Auto-generated method stub
04. return dataList.size();
05. }
06.  
07. @Override
08. public Object getItem(int position) {
09. // TODO Auto-generated method stub
10. return dataList.get(position);
11. }
12.  
13. @Override
14. public long getItemId(int position) {
15. // TODO Auto-generated method stub
16. return position;
17. }

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

01. @Override
02. public int getItemViewType(int position) {
03. // TODO Auto-generated method stub
04. if ("0".equals(dataList.get(position).getMr_type())) {
05. return TYPE_COMSUM;// 消费类型
06. else if ("1".equals(dataList.get(position).getMr_type())) {
07. return TYPE_CHARGE;// 充值类型
08. else {
09. return 100;
10. }
11. }
12.  
13. @Override
14. public int getViewTypeCount() {
15. return TYPE_COUNT;
16. }

viewholder:缓存这几个textview控件

01. /**
02. * 消费记录
03. * @author yl
04. *
05. */
06. class ComsumViewHolder {
07. TextView branchnameCom;
08. TextView comsumemoney;
09. TextView useprevillage;
10. TextView yuezhifu;
11. TextView cash;
12. TextView thisscore;
13. TextView extrareward;
14. TextView prestoremoney;
15. }
16.  
17. /**
18. * 充值记录
19. * @author yl
20. *
21. */
22. class ChargeViewHolder {
23. TextView branchnameCha;
24. TextView prestoremoney;
25. TextView extrasmoney;
26. TextView totalmoney;
27. }


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

1. currentType = getItemViewType(position);

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

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

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

01. public View getView(int position, View convertView, ViewGroup parent) {
02. // TODO Auto-generated method stub
03. View comsumView = null;
04. View chargeView = null;
05.  
06. ComsumAndChargeRecordBean record = (ComsumAndChargeRecordBean) dataList
07. .get(position).getMr_content();
08.  
09. currentType = getItemViewType(position);
10. if (currentType == TYPE_COMSUM) {
11. ComsumViewHolder comsumHolder = null;
12. if (convertView == null) {
13. comsumHolder = new ComsumViewHolder();
14. comsumView = LayoutInflater.from(mContext).inflate(
15. R.layout.traderecord_item_comsume, null);
16. comsumHolder.branchnameCom = (TextView) comsumView
17. .findViewById(R.id.tv_branch_name);
18. comsumHolder.comsumemoney = (TextView) comsumView
19. .findViewById(R.id.tv_comsumemoney);
20. comsumHolder.useprevillage = (TextView) comsumView
21. .findViewById(R.id.tv_useprevillage);
22. comsumHolder.yuezhifu = (TextView) comsumView
23. .findViewById(R.id.tv_yuezhifu);
24. comsumHolder.cash = (TextView) comsumView
25. .findViewById(R.id.tv_cash);
26. comsumHolder.thisscore = (TextView) comsumView
27. .findViewById(R.id.tv_thisscore);
28. comsumHolder.extrareward = (TextView) comsumView
29. .findViewById(R.id.tv_extrareward);
30. comsumView.setTag(comsumHolder);
31. convertView = comsumView;
32. else {
33. comsumHolder = (ComsumViewHolder) convertView.getTag();
34. }
35. comsumHolder.branchnameCom.setText(DateFormatUtil.formatDate(Long
36. .valueOf(dataList.get(position).getMr_createtime()))
37. "  "
38. + record.getBranch_name());// 消费时间和分店
39. comsumHolder.comsumemoney.setText(record.getPay_money());// 消费金额
40. comsumHolder.useprevillage.setText(record.getCoupon());// 使用特权
41. comsumHolder.yuezhifu.setText(record.getMember_money());// 余额支付
42. comsumHolder.cash.setText(record.getCash());// 现金支付
43. comsumHolder.thisscore.setText(record.getPoint());// 本次积分
44. comsumHolder.extrareward.setText(record.getBonus());// 额外奖励
45. else if (currentType == TYPE_CHARGE) {
46. ChargeViewHolder chargeHoler = null;
47. if (convertView == null) {
48. chargeHoler = new ChargeViewHolder();
49. chargeView = LayoutInflater.from(mContext).inflate(
50. R.layout.traderecord_item_chongzhi, null);
51. chargeHoler.branchnameCha = (TextView) chargeView
52. .findViewById(R.id.tv_branchname_charge);
53. chargeHoler.prestoremoney = (TextView) chargeView
54. .findViewById(R.id.tv_prestoremoney);
55. chargeHoler.extrasmoney = (TextView) chargeView
56. .findViewById(R.id.tv_extrasmoney);
57. chargeHoler.totalmoney = (TextView) chargeView
58. .findViewById(R.id.tv_totalmoney);
59. chargeView.setTag(chargeHoler);
60. convertView = chargeView;
61. else {
62. chargeHoler = (ChargeViewHolder) convertView.getTag();
63. }
64.  
65. chargeHoler.branchnameCha.setText(DateFormatUtil.formatDate(Long
66. .valueOf(dataList.get(position).getMr_createtime()))
67. " "
68. + record.getBranch_name());// 消费时间和分店
69. // chargeHoler.prestoremoney.setText(record.getPrestore_money() +
70. // "元");// 存款
71. chargeHoler.extrasmoney.setText(record.getMember_money() + "元");// 余额
72. chargeHoler.totalmoney.setText(record.getMember_money() + "元");// 合计
73. }
74. return convertView;
75. }

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

四、总结

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

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

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

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

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


转自:http://www.it165.net/pro/html/201406/16181.html

另外一篇简单的例子:http://blog.csdn.net/jdsjlzx/article/details/8273661


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值