ListView自定义Adapter点击行改色后滚动时颜色错位问题求助
解决ListView自定义Adapter点击行变色后滚动错位的问题
这个问题太常见了——本质是ListView的View复用机制在搞鬼!当你上下滚动列表时,已经滑出屏幕的行View会被重新拿来复用给新进入屏幕的行,如果只是在点击时直接修改View的颜色,没有把选中状态和对应的数据绑定,复用的View就会带着之前的颜色“跑”到其他行上,导致颜色错位。
下面是具体的解决步骤和代码修改方案:
1. 给数据模型添加选中状态字段
首先,要把“是否选中”这个状态和你的数据绑定在一起,而不是只存在View里。比如你的数据模型可以改成这样:
public class YourDataModel { // 你的原有业务字段 public string Description { get; set; } // 新增:标记当前项是否被选中 public bool IsSelected { get; set; } = false; }
2. 在列表点击事件中更新选中状态并刷新列表
在你设置ListView的Item点击事件时,更新对应位置数据的选中状态,然后通知Adapter刷新:
// 假设你的ListView实例是listView,数据源是yourDataList,Adapter是yourAdapter listView.ItemClick += (sender, e) => { // 如果是单选需求:先取消所有项的选中状态 foreach (var item in yourDataList) { item.IsSelected = false; } // 设置当前点击项为选中状态 yourDataList[e.Position].IsSelected = true; // 通知Adapter刷新列表,让新的状态生效 yourAdapter.NotifyDataSetChanged(); }; // 如果是多选需求,就不用取消其他项,直接切换当前项的状态: // yourDataList[e.Position].IsSelected = !yourDataList[e.Position].IsSelected; // yourAdapter.NotifyDataSetChanged();
3. 修改GetView方法,根据数据状态设置颜色
在Adapter的GetView方法里,每次创建或复用View时,都要根据当前数据的IsSelected状态来设置行的颜色,覆盖复用View的旧状态:
public override View GetView(int position, View convertView, ViewGroup parent) { DataViewHolder holder = null; // 获取当前位置对应的数据 var currentItem = yourDataList[position]; if (convertView == null) { convertView = LayoutInflater.From(mContext).Inflate(Resource.Layout.TableItems, null, false); holder = new DataViewHolder(); holder.txtDescription = convertView.FindViewById<TextView>(Resource.Id.txtDescription); // 初始化其他控件... convertView.Tag = holder; } else { holder = convertView.Tag as DataViewHolder; } // 设置业务内容 holder.txtDescription.Text = currentItem.Description; // 关键:根据数据的选中状态设置行背景色 if (currentItem.IsSelected) { convertView.SetBackgroundColor(Color.ParseColor("#FFE0E0")); // 选中时的颜色,可自定义 } else { convertView.SetBackgroundColor(Color.White); // 默认背景色,和你的布局保持一致 } return convertView; }
为什么这样能解决问题?
因为我们把“选中状态”从View转移到了数据模型里——每次GetView都会根据当前行对应的数据来设置颜色,不管这个View是不是复用的,都能保证显示的状态和数据匹配,彻底解决滚动时的颜色错位问题。
内容的提问来源于stack exchange,提问作者daddycool
相关产品推荐
相关产品推荐

