You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListView滚动时为何会重置已修改的列表项?

解决ListView点击更新后滚动恢复默认值的问题

嘿,这个问题我太熟了!本质是你只改了UI上的显示,没同步更新数据源,加上ListView的复用机制在捣乱,给你一步步解决:

1. 先给实体类加状态字段

你的CategoryPreviewClass现在只有名称和ID,没有存储修改后的状态(比如是否选中、修改后的名称),所以滚动时Adapter只能拿到原始数据。先扩展实体类:

public class CategoryPreviewClass { 
    public string CategoryName { get; set; } 
    public string CategoryID { get; set; }
    // 新增字段存状态,比如是否选中(根据你的需求调整)
    public bool IsSelected { get; set; } = false;
    // 如果是修改名称,就加个显示用的字段
    public string DisplayName { get; set; }
}

2. 点击列表项时,更新数据源+通知Adapter

点击时别只改View,要找到对应的数据对象修改,然后告诉Adapter数据变了:

// 假设你的ListView是listView,数据源是List<CategoryPreviewClass> categoryList
listView.ItemClick += (sender, e) => {
    // 获取点击位置的实体对象
    var targetCategory = categoryList[e.Position];
    // 这里根据你的需求修改状态,比如切换选中状态
    targetCategory.IsSelected = !targetCategory.IsSelected;
    // 如果是改名称:targetCategory.DisplayName = "修改后的名称";
    // 关键!通知Adapter更新UI
    yourCustomAdapter.NotifyDataSetChanged();
};

3. 修改Adapter的GetView方法,用最新数据源渲染

ListView滚动时会复用View,所以GetView里必须从数据源取最新状态,不能用默认值:

public override View GetView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    ViewHolder holder;

    // 复用View+ViewHolder优化性能
    if (row == null) {
        row = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.你的列表项布局, parent, false);
        holder = new ViewHolder();
        holder.categoryNameTv = row.FindViewById<TextView>(Resource.Id.tv_category_name);
        // 其他控件比如CheckBox、ImageView也放这里
        row.Tag = holder;
    } else {
        holder = (ViewHolder)row.Tag;
    }

    // 拿到当前位置的最新数据
    var currentItem = categoryList[position];

    // 根据最新数据设置UI
    if (currentItem.IsSelected) {
        holder.categoryNameTv.SetTextColor(Color.Red); // 选中样式
        // 比如如果有CheckBox:holder.selectCb.Checked = true;
    } else {
        holder.categoryNameTv.SetTextColor(Color.Black); // 默认样式
        // holder.selectCb.Checked = false;
    }
    // 如果是修改名称,优先用DisplayName,没有就用原始名称
    holder.categoryNameTv.Text = currentItem.DisplayName ?? currentItem.CategoryName;

    return row;
}

// ViewHolder类,避免重复查找控件
private class ViewHolder {
    public TextView categoryNameTv;
    // 其他控件声明,比如CheckBox selectCb;
}

为什么之前会出问题?

ListView的convertView是复用机制,滚动时会把滑出屏幕的View重新拿来用,如果你没把修改后的状态存在数据源里,GetView每次都会从原始的、未修改的CategoryPreviewClass对象取数据,自然就恢复默认了。核心原则:UI的状态永远从数据源读取,修改UI前先改数据源。

内容的提问来源于stack exchange,提问作者testsc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:25:46