20150526

listview是常用的控件,经常用自定义的adapter,为了提高显示效率,常利用view的重用方式防止重绘,但因为重用利用的是旧的view,常导致显示的数据会由于position的位置出现错乱。在一个app项目中我遇到过多次这个问题,包括带Button的都能很好的解决,但今天遇到listview中的item有togglelbutton的情况,绑定的监听器是togglebutton的CompoundButton.OnCheckedChangeListener(),竟然出现了问题,一直没有解决,最后将item的监听换成了View.OnClickListener()才解决问题。

一般,为了防止数据混乱,会在convertview判断null的if-else之后再获取list里的显示数据。getview的例子如下:

     @Override
public View getView(int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
final ViewHolder holder;
// 优化listview --去掉重用,防止togglebutton的点击位置记录出错
if(convertView == null)
{
// 使用自定义的布局
holder = new ViewHolder();
convertView = mInflater
.inflate(R.layout.list_invite_party_member, null);
// 初始化布局中的元素
holder.ivAvatar = (ImageView) convertView.findViewById(R.id.iv_avater);
holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
holder.tvTag = (TextView) convertView.findViewById(R.id.tv_tag);
holder.btnSelect = (ToggleButton) convertView
.findViewById(R.id.btn_select);
holder.linearLayout = (LinearLayout) convertView
.findViewById(R.id.rl_friend_item);
convertView.setTag(holder);
} else
{
holder = (ViewHolder)convertView.getTag();
} // 绑定数据
final int index = position;
UserBean bean = listFriend.get(index);
// 设置头像
if (!TextUtils.isEmpty(bean.getUserAvatar()))
{
String avatarUrl = Constant.URL_USER_AVATER + bean.getUserAvatar();
// 初始化异步加载头像对象
finalBitmap = FinalBitmap.create(context);
finalBitmap.configLoadingImage(R.drawable.user_head_02);
finalBitmap.display(holder.ivAvatar, avatarUrl);
} else
{
holder.ivAvatar.setImageResource(R.drawable.user_head_02);
} if (!TextUtils.isEmpty(bean.getUserNickname()))
{
holder.tvName.setText(bean.getUserNickname());
} else
{
holder.tvName.setText(bean.getUserPhone());
}
if (!TextUtils.isEmpty(CommonUtils.getUserTags(bean)))
{
holder.tvTag.setText(CommonUtils.getUserTags(bean));
holder.tvTag.setVisibility(View.VISIBLE);
} else
{
holder.tvTag.setVisibility(View.GONE);
}
if (TextUtils.equals(bean.getReserved01(), "1"))
{
// 已添加的场合显示为 删除
holder.btnSelect.setChecked(true);
} else
{
holder.btnSelect.setChecked(false);
}
holder.btnSelect.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
ToggleButton view = (ToggleButton)v;
//boolean isCheckedOld = view.getText().toString().equals("添加")?true:false;
// 获取最新的点击后check状态
boolean isChecked = view.isChecked();
if (isChecked)
{
// 添加了该人,button显示删除
view.setChecked(true);
listFriend.get(index).setReserved01("1"); } else
{
// 原来是被选中的,点击后该人被删除
// 删除了该人,button显示添加
view.setChecked(false);
listFriend.get(index).setReserved01("0");
}
}
});
/* holder.btnSelect
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{ @Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
{ LogUtil.d("isChecked= " + isChecked );
LogUtil.d("index= " + index );
// TODO Auto-generated method stub
if (isChecked)
{
// 添加了该人,button显示删除
listFriend.get(index).setReserved01("1");
} else
{
// 删除了该人,button显示添加
listFriend.get(index).setReserved01("0");
}
}
});*/
return convertView;
} /**
* 布局中的元素
*/
class ViewHolder
{
ImageView ivAvatar;
TextView tvName;
TextView tvTag;
ToggleButton btnSelect;
LinearLayout linearLayout;
}

并且用final的index记住了数据的位置,在下面button监听的动作中就可以获得正确的数据了。

但是试验发现(注释掉的部分)利用此方法还是不可以,可能是CompoundButton.OnCheckedChangeListener()的问题吧。利用此监听器监听button的动作改变list相应数据会导致位置混乱。只好借用View.OnClickListener()来控制togglebutton的显示了。倒也不算麻烦,本来togglebutton就一般是这两种控制方式。还有要注意的是只要点击的togglebutton,它的check状态就会变,在View.OnClickListener()中也是一样。

mark一下,所以利用adapter记住btn的状态这件事还是很简单的,就是没有理解到CompoundButton的机制而导致的失败,还好有View.OnClickListener()成功的先例,要不然每个view都绘制list数据很多的话也太不现实了。还有一个checkbox的item没有尝试,不行的话还是要用button或View.OnClickListener()来替代了。

android listview 重用view导致的选择混乱问题的更多相关文章

  1. Android ListView 中加入CheckBox/RadioButton 选择状态保持、全选、反选实现

    最近在一个项目中,需要在ListView的item中加入CheckBox,但是遇到的一个问题是上下滑动的时候如果有选择了的CheckBox,就会出现选择项错误的问题,下面将个人的解决方法总结如下;先说 ...

  2. Android ListView 显示多种数据类型

    ListView往往可能会有不同的数据类型,单类型的数据可能运用会比较少些,这也是最近项目中的一个需求{在发送消息的时候,需要选择联系人,而联系人列表由英文字母索引+联系人组成},上一篇文章只是一个基 ...

  3. Android ListView批量选择(全选、反选、全不选)

    APP的开发中,会常遇到这样的需求:批量取消(删除)List中的数据.这就要求ListVIew支持批量选择.全选.单选等等功能,做一个比较强大的ListView批量选择功能是很有必要的,那如何做呢? ...

  4. android 修改listview item view 的方法(转)

    android 修改listview item view 的方法   具体的解答办法很简单: 代码如下 : 1.获取需要更新的view int visiblePosition = mListView. ...

  5. Android精通:View与ViewGroup,LinearLayout线性布局,RelativeLayout相对布局,ListView列表组件

    UI的描述 对于Android应用程序中,所有用户界面元素都是由View和ViewGroup对象构建的.View是绘制在屏幕上能与用户进行交互的一个对象.而对于ViewGroup来说,则是一个用于存放 ...

  6. Android ListView getView()方法重复调用导致position错位

    问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...

  7. 【Android UI】Android开发之View的几种布局方式及实践

    引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...

  8. 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d3e3ab10c62013697408 作者:黄宁源 一,背景 Recy ...

  9. Android listview与adapter用法

    listview与adapter用法 博客分类: android   一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView ...

随机推荐

  1. C/C++各种系统开发环境搭建

    http://pan.baidu.com/s/1qWJKF4g

  2. libiconv_百度百科

    libiconv_百度百科   由于历史原因,国际化的文字常常由于语言或者国家的原因使用不同的编码.目录     1libiconv历史简介     2libiconv编码简介     3libico ...

  3. SPFA,dijskra,prime,topu四种算法的模板

    ////#include<stdio.h> ////#include<string.h> ////#include<queue> ////#include<a ...

  4. 【Android Tricks 6】ViewPager首页与尾页的滑动动作响应

    ViewPager能够说是Android应用中使用比較广发的一个组件了.它能够帮助我们非常 方便地实现滑动更换View的效果.刚好近期搞的一个项目有一个需求用到了这个,同 时是要能在首页和尾页滑动时可 ...

  5. C++关注备注部分知识点

    //关注备注部分知识点. #include <iostream> #include <string><span style="white-space:pre&q ...

  6. C# 中4个访问符和8个修饰符详解

    4个访问修饰符(是添加到类.结构或成员声明的关键字) Public:公有的,是类型和类型成员的访问修饰符.对其访问没有限制. Internal:内部的,是类型和类型成员的访问修饰符.同一个程序集中的所 ...

  7. UIlabel添加背景图片

    做UI的时候我们可能想给某个Label添加一个背景图片,但查看的时候会发现好像只有设置背景颜色的方法,不过我们也可以通过这种方式来解决: UIColor *color = [UIColor color ...

  8. CTreeCtrl点击获得选中项

    相应TVN_SELCHANGED可以得到选中的项,在相应函数内如下: LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(p ...

  9. Assets理解随笔

    在PlayFramework中应用 在Play框架中提供的都是动态文件响应,前端工作内容大部分是静态文件.Assets大概起的就是这个作用. 默认路径看 conf/routes 里: # Map st ...

  10. composer时间长了,提示需要升级,结果问题来了

    今天重新开始之前的laravel项目,结果composer提示需要升级,于是 composer selfupdate 结果提示无法连接目标库,查阅composer官网,发现之前的库地址已经启用了ssl ...