在开发的过程中我们经常会遇到这样的需求:在ListView的每个Item中保存一些用户编辑的过的状态,比如CheckBox,EditText等,这些这些状态要保证在正常滑动的时候,不会出现错乱的情况。
现在需求清楚了,我们来思考一下解决方案。我们的方案很简单,就是将用户编辑过的信息保存在一个Map对象中,用position作为Key保存下来,然后建一个ViewHolder来实现复用,为需要保存状态的对象设置一个Tag,这个Tag就是position,最后在每次系统调用getView()方法是,我们依据这个Tag去Map里面找,如果有我们将其还原即可。
好了思路捋清楚了,下面我们开始看代码吧:
1 package org.vincenttang.test.adapter; 2 3 import android.content.Context; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.BaseAdapter;; 8 import android.widget.CheckBox; 9 import android.widget.CompoundButton; 10 import android.widget.TextView; 11 12 import org.vincenttang.test.R; 13 import java.util.ArrayList; 14 import java.util.HashMap; 15 16 17 /** 18 * Created by VincentTang <br/> 19 * Author: VincentTang <br> 20 * Email: 1654844600@qq.com <br/> 21 * Date: 2016/1/10 <br/> 22 * Instruction: 23 */ 24 public class ListAdapter extends BaseAdapter { 25 private Context context; 26 private ArrayList<String> list; 27 private HashMap<Integer, Boolean> record; 28 29 30 public ListAdapter(Context context, ArrayList<String> list) { 31 //构造方法初始化 32 this.context = context; 33 this.list = list; 34 this.record = new HashMap<>(); 35 } 36 37 @Override 38 public int getCount() { 39 return list.size(); 40 } 41 42 @Override 43 public Object getItem(int position) { 44 return list.get(position); 45 } 46 47 @Override 48 public long getItemId(int position) { 49 return position; 50 } 51 52 @Override 53 public View getView( final int position, View convertView, ViewGroup parent){ 54 //viewHolder 复用视图的引用 55 ViewHolder viewHolder = null; 56 //如果没有复用的视图从新创建 57 if (convertView == null) { 58 convertView = LayoutInflater.from(context).inflate(R.layout.list_item_test, parent, false); 59 viewHolder = new ViewHolder(); 60 viewHolder.cb = (CheckBox) convertView.findViewById(R.id.cb); 61 viewHolder.txtTest = (TextView) convertView.findViewById(R.id.txt_test); 62 convertView.setTag(viewHolder); 63 //这里给对应的空间设置一个Tag,回复的时候们要用这个 64 viewHolder.cb.setTag(position); 65 } else { 66 viewHolder = (ViewHolder) convertView.getTag(); 67 //这里给对应的空间设置一个Tag,回复的时候们要用这个 68 viewHolder.cb.setTag(position); 69 } 70 //设置测试数据 71 viewHolder.txtTest.setText(list.get(position)); 72 73 //设置时间监听,当用户操作是,根据情况记录和删除 74 viewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 75 @Override 76 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 77 if (isChecked) { 78 //选中的时候记下 79 record.put(position, isChecked); 80 }else { 81 //取消选中时删除 82 record.remove(position); 83 } 84 } 85 }); 86 87 //还原状态 88 viewHolder.cb.setChecked(record.get(viewHolder.cb.getTag()) == null ? false : true); 89 90 return convertView; 91 } 92 93 /** 94 * 复用的Holder 95 */ 96 class ViewHolder { 97 CheckBox cb;//需要记录状态的空间 98 TextView txtTest;//显示测试数据 99 } 100 101 }
其实好简单,是吧。
为了我们测试,我们模拟了很多数据:
1 package org.vincenttang.test; 2 3 import android.content.Intent; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.AbsListView; 8 import android.widget.ArrayAdapter; 9 import android.widget.Button; 10 import android.widget.ListView; 11 12 import org.vincenttang.test.adapter.ListAdapter; 13 14 import java.util.ArrayList; 15 import java.util.Objects; 16 17 18 public class MainActivity extends AppCompatActivity { 19 //数据展示的ListView 20 private ListView listView; 21 22 @Override 23 protected void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_main); 26 initView(); 27 initData(); 28 29 } 30 31 /** 32 * 关联控件 33 */ 34 private void initView() { 35 listView = (ListView) findViewById(R.id.list_view); 36 } 37 38 /** 39 * 初始化数据 40 */ 41 private void initData(){ 42 ArrayList<String> list = new ArrayList<>(); 43 for (int i = 0; i < 500; i++) { 44 list.add("item"+i); 45 } 46 ListAdapter adapter = new ListAdapter(this,list); 47 48 listView.setAdapter(adapter); 49 50 } 51 52 }