在列表视图自定义适配器中编辑文本在滚动时失去其位置?——Xamarin.Android

本文关键字:失去 位置 Android Xamarin 滚动 视图 列表 自定义 适配器 编辑 文本 | 更新日期: 2023-09-27 18:15:33

当我们在第一行输入value时,当我们滚动到第6行时,在第1行输入的值会出现在第6行。请参阅以下代码和建议。

namespace Kites
{
public class Marks 
{
    // add any if you need more
    public string StudentName { get; set; }
    public string MarksScored { get; set; }
}
public class TEXTCHECK
{
    public int POS { get; set; }
    public string Value { get; set; }
}
public class MarksListViewAdapter : BaseAdapter<Marks>
{
    private List<Marks> mstuduentmarks;
    private List<TEXTCHECK> abc = new List<TEXTCHECK>();
    private Context mcontext;
    public MarksListViewAdapter (Context context, List<Marks> stud)
    {
        mstuduentmarks = stud;
        mcontext = context;
    }
    public override int Count 
    {
        get 
        {
            return mstuduentmarks.Count;
            //              return mattendence.Count;
        }
    }
    public override long GetItemId (int position)
    {
        return position;
    }
    public override Marks this[int position] 
    {
        get 
        {
            return mstuduentmarks [position];
            //              return mattendence [position];
        }
    }
    class ViewHolder : Java.Lang.Object
    {
        public EditText comsevin;
        public TextView namenmn;
    }
    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder;
        View view = convertView;
        if (view == null) // otherwise create a new one
        {
            view = LayoutInflater.From(mcontext).Inflate(Resource.Layout.listview_Marks, null, false);
            holder = new ViewHolder();
            holder.comsevin = view.FindViewById<EditText>(Resource.Id.editTextTeacherMarks);
            holder.namenmn = view.FindViewById<TextView>(Resource.Id.textStudentNameTeacherMarks);
            holder.namenmn.Tag = position;
            view.Tag = holder;
        }
        else
        {
            holder = (ViewHolder)view.Tag;
        }
        holder.namenmn.Text = mstuduentmarks[position].StudentName;
        int pos = (int)holder.namenmn.Tag;
        holder.comsevin.TextChanged += (sender, e) =>
        {
            abc[pos].Value = holder.comsevin.Text;
        };
        //TextView txtStudent = 
        //txtStudent.Text = mstuduentmarks[position].StudentName;

        //txtMarks.FocusChange += (object sender, View.FocusChangeEventArgs e) =>
        //{
        //      //txtMarks.RequestFocusFromTouch ();
        //      mstuduentmarks[position].MarksScored = txtMarks.Text;
        //};

        holder.comsevin.BeforeTextChanged += (sender, e) =>
        {
            abc.Add(new TEXTCHECK { POS = position, Value = mstuduentmarks[position].MarksScored }); 
        };
        holder.comsevin.AfterTextChanged += (sender, e) => 
        {
            int a = abc[pos].POS;
            mstuduentmarks[pos].MarksScored = abc[pos].Value;
        };

        //txtMarks.Tag = position;
        //txtMarks.TextChanged += TxtMarks_TextChanged;
        return view;
    }
    //void TxtMarks_TextChanged (object sender, Android.Text.TextChangedEventArgs e)
    //{
    //  EditText txtMarks = (EditText)sender;
    //  //var position = (int)txtMarks.Tag;

    //}
}
}

当我们在第一行输入value时,当我们滚动到第6行时,在第1行输入的值会出现在第6行。请参阅以下代码和建议

在列表视图自定义适配器中编辑文本在滚动时失去其位置?——Xamarin.Android

作为一个经验法则,当遇到列表不反映数据集(例如经历项目重复)在listview/recyclerview这意味着你要么使用脏视图,以前使用过,然后不正确地重新绑定,或者只是使用错误的位置在绑定

我知道你哪里搞错了:

if (view == null) // otherwise create a new one
        {
            view = LayoutInflater.From(mcontext).Inflate(Resource.Layout.listview_Marks, null, false);
            holder = new ViewHolder();
            holder.comsevin = view.FindViewById<EditText>(Resource.Id.editTextTeacherMarks);
            holder.namenmn = view.FindViewById<TextView>(Resource.Id.textStudentNameTeacherMarks);

            holder.namenmn.Tag = position;//<------------here!!!
            view.Tag = holder;
        }

TLDR不要这样保存位置

发生了什么:你的视图的这个实例被listView重用,这意味着有时(很多次)if (view == null)将是假的,这意味着标签属性将不会被更新为第6行(或任何其他调用将使用回收视图),你实际上是使用一个脏值。

你然后试图使用Tag属性作为位置,但忘记这个标签已经脏了,如果视图被回收

int pos = (int)holder.namenmn.Tag;
        holder.comsevin.TextChanged += (sender, e) =>
        {
            abc[pos].Value = holder.comsevin.Text;
        };

因为你可以在这个方法调用中访问位置,所以你应该直接使用它

看一看这个来自Java代码极客的指南,尽管它是用Java编写的,你还是可以看到一个很好的老式ViewHolder/ListView模式的实现。


希望能有所帮助