题外话:
Adapter中的GetView没有经过优化的代码:
<pre name="code" class="csharp">using System;using System.Collections.Generic;using System.Linq;using System.Text;using Android.App;using Android.Content;using Android.OS;using Android.Runtime;using Android.Views;using Android.Widget;using Java.Lang;using DeBug = System.Diagnostics.Debug;namespace DrawerLayout.Adapter{ public class News { public int Pv { get; set; } public string Title { get; set; } public News(string title,int Pv) { this.Title = title; this.Pv = Pv; } } public class NewsAdapter : BaseAdapter { private List<News> data; private Context context; public override int Count { get { return data.Count; } } public NewsAdapter(List<News> data,Context context) { this.data = data; this.context = context; } public override Java.Lang.Object GetItem(int position) { return null; } public override long GetItemId(int position) { return position; } private int count; public override View GetView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.From(context).Inflate(Resource.Layout.lv_test,parent,false); TextView title = convertView.FindViewById<TextView>(Resource.Id.tv_title); TextView pv = convertView.FindViewById<TextView>(Resource.Id.tv_pv); CheckBox chk = convertView.FindViewById<CheckBox>(Resource.Id.chk_test); pv.Text = data[position].Pv.ToString(); title.Text = data[position].Title; DeBug.Write($"执行GetView第{position}次");//DeBug.Write直接在输出里面看到到底发生了什么 DeBug.Write(dictChk[position]); return convertView; } }}Xamarin android中ListView中的CheckBox在滑动的时候失去状态的根本原因:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Android.App;using Android.Content;using Android.OS;using Android.Runtime;using Android.Views;using Android.Widget;using Java.Lang;using DeBug = System.Diagnostics.Debug;namespace DrawerLayout.Adapter{ public class News { public int Pv { get; set; } public string Title { get; set; } public News(string title,int Pv) { this.Title = title; this.Pv = Pv; } } public class NewsAdapter : BaseAdapter { private List<News> data; private Context context; private Dictionary<int, bool> dictChk = new Dictionary<int, bool>(); public override int Count { get { return data.Count; } } public NewsAdapter(List<News> data,Context context) { this.data = data; this.context = context; for (int i = 0; i < data.Count; i++) { dictChk.Add(i,false); } } public override Java.Lang.Object GetItem(int position) { return null; } public override long GetItemId(int position) { return position; } private int count; public override View GetView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.From(context).Inflate(Resource.Layout.lv_test,parent,false); TextView title = convertView.FindViewById<TextView>(Resource.Id.tv_title); TextView pv = convertView.FindViewById<TextView>(Resource.Id.tv_pv); CheckBox chk = convertView.FindViewById<CheckBox>(Resource.Id.chk_test); pv.Text = data[position].Pv.ToString(); title.Text = data[position].Title; chk.Checked = dictChk[position];//每一个Checkbox是否选中是直接根据dicChk的key(position)获取是否选中 chk.CheckedChange += (s, e) => { dictChk[position] = e.IsChecked;//每一次单击CheckBox,dictChk都会保存单击哪一个(position)的状态 }; DeBug.Write($"执行GetView第{position}次");//DeBug.Write直接在输出里面看到到底发生了什么 DeBug.Write(dictChk[position]); return convertView; } }}效果图:
这样肯定不行啊!!一般ListView中的控件都会加一个类 ViewHolder来优化啊.
public override View GetView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = LayoutInflater.From(context).Inflate(Resource.Layout.lv_test, parent, false); holder = new ViewHolder(); holder.tv_title = convertView.FindViewById<TextView>(Resource.Id.tv_title); holder.tv_pv = convertView.FindViewById<TextView>(Resource.Id.tv_pv); holder.chk_status = convertView.FindViewById<CheckBox>(Resource.Id.chk_test); convertView.Tag = holder; } else { holder = (ViewHolder)convertView.Tag; } holder.tv_pv.Text = data[position].Pv.ToString(); holder.tv_title.Text = data[position].Title; DeBug.Write($"执行GetView第{position}次"); DeBug.Write(dictChk[position]); return convertView; } public override View GetView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; News item = data[position]; if (convertView == null) { convertView = LayoutInflater.From(context).Inflate(Resource.Layout.lv_test, parent, false); holder = new ViewHolder(); holder.tv_title = convertView.FindViewById<TextView>(Resource.Id.tv_title); holder.tv_pv = convertView.FindViewById<TextView>(Resource.Id.tv_pv); holder.chk_status = convertView.FindViewById<CheckBox>(Resource.Id.chk_test); convertView.Tag = holder; } else { holder = (ViewHolder)convertView.Tag; } holder.chk_status.Tag = position; holder.tv_pv.Text = data[position].Pv.ToString(); holder.tv_title.Text = data[position].Title; <span style="color:#FF0000;">holder.chk_status.Checked = dictChk[(int)holder.chk_status.Tag];</span> holder.chk_status.CheckedChange += (s, e) => { DeBug.Write((int)holder.chk_status.Tag); <span style="color:#FF0000;">dictChk[(int)holder.chk_status.Tag] = e.IsChecked;</span> }; DeBug.Write($"执行GetView第{position}次"); DeBug.Write(dictChk[position]); return convertView; }position参数的误区:
加上上面两行红色的代码就可以完全解决listView滑动时失去ChecxBox状态的bug了,刚开始学的时候不能理解这个bug是因为这个GetView中的position参数,当你刚学会用这个listview的时候你一定以为position不就是有多少条数据就多大吗?但是实际却是完全相反的,你手机能显示6条数据。position一直都是0-5,当你滑动到2-7的数据时,position还是0-5。还有CheckBox的状态也可以用用实体字段来保存.
Android中Tag是什么
既然不能position来做标识,那就用Tag。这样问题似乎简单多了,好像并没有想象中的复杂啊。简单点说,Tag的作用是和Id的作用是一样的,程序中调用对应的控件用(findViewById(R.tag.chk),findViewByTag(R.tag.chk))!不过和使用tag相比,使用Id进行查找!效率更快!但是在xamarin android中好像没有Tag这种查找控件的方式.
所以我们就要用Tag来保存这个每一个CheckBox的状态
<span style="color:#FF0000;">holder.chk_status.Checked = dictChk[(int)holder.chk_status.Tag];</span>看到这里是不是觉得很简单啊!!!!嘻嘻。
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。



