2012-7-18 在ListView中显示不同的ITEM

二,在ListView中显示不同的ITEM

阅读本节,默认读者已经了解基本的ListView的优化技巧: ViewHolder, ConvertView

前边提到Ophone的ListView实现中有一个BUG。在我开发的过程中,使用了ListView的Header,放置两个按钮用来跳转到推荐的内容和“掌上应用汇”中的类似,它有4个按键用来导航到推荐的内容。‍‍

我使用的设备有5维的导航键,如果你一直用手操作,是不会出现任何问题的,因为手机一直处于TOUCH-MODE,如果用导航键,就会切换到NONE-TOUCH-MODE,不断按向下键切换到HEADER不可见,然后再不断按向上键切换到HEADER可见,这时上图中的4个按钮就会出现问题,表现为无法再收到onClick事件,而且按钮的按下的背景也无法显示(在正常的情况下一个按钮被按下时,会有黄色高亮)。在我的应用和“掌上应用汇”中都可以重现这个问题。可见Ophone中的ListView在处理HEADER View时存在bug,同样的应用程序在HTC Desire with MIUI上表现正常。

你可以使用本节介绍的内容来跳过这个bug,把要显示的View做为List中的第一个ITEM来模拟header效果。

而且我们的最终目标是

可以看到图中包含3中不同的ITEM

a) 灰色的title部分

b) 普通的条目

c) 当前title中更为详细”更多“

因为在ListView调用Adapter的

public View getView(int position, View convertView, ViewGroup parent);

方法时,会把已经不可见的条目传回来,这样的好处是你不用创建一个新的View,只要使用传入的View,更新上面的内容就可以了,这样做可以大大的节约内存资源。

使用的方法就是判断convertView是否为null,如果不为null就使用,如果为null就创建新的。

在我未了解Adapter的机制前,为了实现返回3种不同的View,我写了一个FrameLayout,里面同时有这3种ITEM,只是根据不同的类型来改变不同View的setVisibility为GONE或者VISIBLE。

<pre>public View getView(int position, View convertView, ViewGroup parent){

 if(convertView == null){

convertView = inflater.inflate(R.layout.layout, parent, false);// 仅创建一个包含title, normal, more的整个的view

holder= new ViewHolder();

holder.title = convertView.findViewById(R.id.title);

// 省略的一些

convertView.setTag(holder);

} else {

holder= (ViewHolder)convertView.getTag();

}

Item item = getItem(position);

switch(item.getType()){

case TITLE:

holder.title.setVisibility(VISIBLE);

holder.normal.setVisibility(GONE);

holder.more.setVisibility(GONE);

holder.title.setText(item.title);

break;

// 省略的一些

}

}

</pre>

通过这种方法也能实现,而且使用convertView,效率也不算太差。缺点也很明显,明明创建了3套View,只是使用其中的1/3,如果有更多种,那就更浪费了。

其实ListView和Adapter早就已经为这种情况考虑到了,ListView在传回convertView时已经考虑到,对于不同的类型就缓存在不同的队列中,在调用时传回。请参考Adapter的如下方法:

public int getViewTypeCount();

public int getItemViewType(int position);

所以我们只要修改下adapter的实现就可以节约不少的资源。

修改后的:

public int getViewTypeCount(){

return TOTAL_TYPE_COUNT; //TOTAL_TYPE_COUNT = 3

}

public int getItemViewType(int position){

return getItem(position).getType();

}

public View getView(int position, View convertView, ViewGroup parent){

Item item = getItem(position);

switch(item.getType()){

case TITLE:

if(convertView == null){

convertView = inflater.inflate(R.layout.layout_title, parent, false); // 仅创建一个包含title的View

holder= new ViewHolder();

holder.title = convertView.findViewById(R.id.title);

convertView.setTag(holder);

} else {

holder= (ViewHolder)convertView.getTag();

}

holder.title.setText(item.title);

break;

// 省略的一些

}

}

 

如果模拟header的话就修改TOTAL_TYPE_COUNT = 4,再添加一种type就可以了,而且可以把这个header放到你想要的任何位置。这样就可以跳过那个bug.


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值