所以我一直在开发一个带有复选框的列表视图的应用程序,当我选择一个项目后,当我向下滚动第一个项目时,我注意到列表中的第一个项目向下滚动整页也会选中复选框。我有一种感觉,这是由于重新评估的观点,但我对此解决方案感到好奇。我曾尝试添加一个视图,但这并没有解决问题。只是想知道我错过了什么。适配器上的getview代码如下:
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
Android.Views.View view = convertView;
if (view == null)
{
view = context.LayoutInflater.Inflate(Resource.Layout.GroupTimeTrackerTemplate, parent, false);
}
tblWorkers item = this[position];
view.FindViewById<TextView>(Resource.Id.UserNameTextView).Text = this[position].nWorkerFirstname + " " + this[position].nWorkerLastname;
view.FindViewById<TextView>(Resource.Id.StatusTextView).Text = this[position].nStatusShort;
view.FindViewById<TextView>(Resource.Id.UserRoleTextView).Text = this[position].nTitle;
CheckBox chkSelect = view.FindViewById<CheckBox>(Resource.Id.ChkSelect);
chkSelect.Tag = item.nWorkerFirstname + " " + item.nWorkerLastname;
chkSelect.SetOnCheckedChangeListener(null);
chkSelect.SetOnCheckedChangeListener(new CheckChangeListener(this.context));
return view;
}
private class CheckChangeListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
{
private Activity activity;
public CheckChangeListener(Activity activity)
{
this.activity = activity;
}
public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
{
if (isChecked)
{
string name = (string)buttonView.Tag;
string text = string.Format("{0} Checked.", name);
Toast.MakeText(this.activity, text, ToastLength.Short).Show();
}
}
}
答案 0 :(得分:1)
我最终找到了一个具有可与我的动态模型数据一起使用的View Holder的解决方案。以下对我有用的是解决方案!三个要点是业务逻辑对象有一个bool来保持正在检查的项目和视图持有者帮助执行,最后由于视图的重新命名,你不能可靠地使用点击事件中的列表[位置]所以我使用了包装纸!
查看持有人:
private class MyViewHolder : Java.Lang.Object
{
public TextView txtName;
public TextView txtStatus;
public TextView txtTitle;
public CheckBox chkItem;
}
适配器GetView:
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
var item = list[position];
Android.Views.View view = convertView;
MyViewHolder holder;
if (convertView == null)
{
holder = new MyViewHolder();
view = context.LayoutInflater.Inflate(Resource.Layout.GroupTimeTrackerTemplate, null);
holder.chkItem = view.FindViewById<CheckBox>(Resource.Id.ChkSelect);
holder.txtName = view.FindViewById<TextView>(Resource.Id.UserNameTextView);
holder.txtStatus = view.FindViewById<TextView>(Resource.Id.StatusTextView);
holder.txtTitle = view.FindViewById<TextView>(Resource.Id.UserRoleTextView);
view.Tag = holder;
}
else
{
holder = view.Tag as MyViewHolder;
}
holder.chkItem.Checked = item.StatusSelected;
if (holder.chkItem.Checked)
{
holder.chkItem.Enabled = false;
}
else
{
holder.chkItem.Enabled = true;
}
holder.chkItem.Tag = new MyWrapper<int>(position);
holder.txtName.Text = item.nWorkerFirstname + " " + item.nWorkerLastname;
holder.txtStatus.Text = item.nStatusShort;
holder.txtTitle.Text = item.nTitle;
holder.chkItem.Click -= HolderChkItemClick;
holder.chkItem.Click += HolderChkItemClick;
if (statoChk[position] == 0)
{
holder.chkItem.Checked = false;
}
else
{
holder.chkItem.Checked = true;
}
return view;
}
单击“事件”复选框,包装器和数组:
tblWorkers OrigSel = null;
void HolderChkItemClick(object sender, EventArgs e)
{
var chk = sender as CheckBox;
int pos = ((MyWrapper<int>)chk.Tag).value;
tblWorkers selectedWorker = list[pos];
if (Vm.SelectedWorker == null)
{
OrigSel = selectedWorker;
IntentManager.Instance.OriginalSelectedWorker = OrigSel;
Vm.GroupTimeTrackerStatusType = OrigSel.nStatusShort;
}
Vm.SelectedWorker = selectedWorker;
if (chk.Checked)
{
if (selectedWorker.nStatusShort == OrigSel.nStatusShort)
{
statoChk[pos] = 1;
Vm.GroupTimeList.Add(selectedWorker);
}
else
{
statoChk[pos] = 0;
chk.Checked = false;
Toast.MakeText(context, "Please Select Workers with the Same Time Status. Current Status : " + OrigSel.nStatusShort, ToastLength.Long).Show();
}
}
else
{
statoChk[pos] = 0;
Vm.GroupTimeList.Remove(selectedWorker);
if (Vm.GroupTimeList.Count == 0)
{
Vm.SelectedWorker = null;
OrigSel = null;
IntentManager.Instance.OriginalSelectedWorker = null;
Vm.GroupTimeTrackerStatusType = "";
}
}
}
public class MyWrapper<T> : Java.Lang.Object
{
private T _value;
public MyWrapper(T managedValue)
{
_value = managedValue;
}
public T value { get { return _value; } }
}
int[] statoChk;
public int[] StatoCheck
{
get { return statoChk; }
set { statoChk = value; }
}
答案 1 :(得分:0)
虽然我没有亲自通过Xamarin开发Android,但我拥有Android知识,可以帮助您朝着正确的方向发展。
正如您所说,ListView中的行已被回收。问题在于,当你滚动时,会调用OnCheckedChange方法,因为它会回收它在未选择的新行的位置传递的行,但由于它与之前选择的行具有相同的索引。改变它的价值。
例如,如果选中索引为5的方框然后向下滚动,则新行将成为索引为5的行,因此会更改其状态。
这是Android上的常见问题。要解决这个问题,首先需要一个数据结构,通过将其存储在地图或列表中来跟踪已经检查过哪些行。
然后在GetView中确保将复选框状态设置为该位置的内容。
答案 2 :(得分:0)