ListView每每可能會有不一樣的數據類型,單類型的數據可能運用會比較少些,這也是最近項目中的一個需求{在發送消息的時候,須要選擇聯繫人,而聯繫人列表由英文字母索引+聯繫人組成},上一篇文章只是一個基調,這篇是更復雜的狀況;
先看一下效果圖
最開始的時候,打算把兩種數據類型放入一個List<Object>中,參考上一篇隨筆的狀態保持的實現,在代碼寫完了開始測試的時候,發現問題衆多,上下滾動的時候左邊的CheckBox的選擇狀態沒有很好的保存,會出現混亂選擇的狀況,因而參考網上的一些作法{尋找的參考方法並無描述像這樣稍稍複雜點的狀況,都是TextView,沒有狀態的保持,沒有View的重用,因此寫了這篇隨筆}並延伸總結;
MutiTypeAdapter.javajava
public class MutiTypeAdapter extends BaseAdapter { private OnSelectedItemChanged listener; private List<ListItem> list; private LayoutInflater inflater; public MutiTypeAdapter(Context context, List<ListItem> list, OnSelectedItemChanged listener) { super(); this.list = list; inflater = LayoutInflater.from(context); this.listener = listener; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // 重點 View view = list.get(position).getView(convertView, inflater); if (list.get(position).getClass() == BEntity.class) { // 若是是BEntity,也就是上面圖中左邊有CheckBox的項 final BEntity entity = (BEntity) list.get(position); final CheckBox cb = entity.cbox; cb.setChecked(entity.isChecked()); cb.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { entity.setChecked(cb.isChecked()); // 更改List中Entity的選擇狀態 if (listener != null) { listener.onClick(getSelectedItem(list)); // 接口的思想暴露給Activity選擇了多少項,固然也能夠具體點通知Activity選擇了哪些項 } } }); } return view; } public int getSelectedItem(List<ListItem> list) { // 獲取選擇了多少項 int i = 0; for (ListItem item : list) { if (item.isChecked()) { i++; } } return i; } public interface OnSelectedItemChanged { public void onClick(int count); } }
上面是數據源適配器,最開始的時候我在getView方法中對Item進行數據類的判斷(AEntity/BEntity),再決定是選擇加載哪個layout,結果發如今重用View的時候很混亂,因此改成上面的實現方法;
AEntity和BEntity都繼承自接口ListItemide
public class AEntity implements ListItem { private String str; public AEntity(String str) { super(); this.str = str; } @Override public View getView(View convertView, LayoutInflater inflater) { Holder holder = null; if (convertView == null || convertView.getTag().getClass() != Holder.class) { holder = new Holder(); convertView = inflater.inflate(getLayoutId(), null); TextView tv = (TextView) convertView.findViewById(R.id.title_tv); holder.tv = tv; convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); } holder.tv.setText(str); return convertView; } class Holder { TextView tv; } @Override public int getLayoutId() { return R.layout.title; } @Override public boolean isChecked() { // 此Entity至關因而標題項,沒有CheckBox,因此永遠返回false return false; } }
public class BEntity implements ListItem { private boolean isChecked = false; private String str; public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; } public BEntity(String str) { super(); this.str = str; } @Override public int getLayoutId() { return R.layout.child; } public CheckBox cbox; @Override public View getView(View convertView, LayoutInflater inflater) { Holder holder = null; if (convertView == null || convertView.getTag().getClass() != Holder.class) { holder = new Holder(); convertView = inflater.inflate(getLayoutId(), null); TextView tv = (TextView) convertView.findViewById(R.id.item_tv); CheckBox cb = (CheckBox) convertView.findViewById(R.id.item_cb); holder.tv = tv; holder.cb = cb; convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); } holder.tv.setText(str); final CheckBox cb = holder.cb; this.cbox = cb;return convertView; } class Holder { TextView tv; CheckBox cb; } }
ListItem.java測試
public interface ListItem { public boolean isChecked(); // 當前項是否選中 public int getLayoutId(); public View getView(View convertView, LayoutInflater inflater); // 返回Adapter中須要返回的View }
在MainActivity中,模擬數據源並綁定到ListView列表;this
public class MainActivity extends Activity { ListView lv; MutiTypeAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.lv); setAdapter(); } private void setAdapter() { List<ListItem> list = new ArrayList<ListItem>(); for (int i = 0; i < 50; i++) { if (i % 2 == 0) { list.add(new AEntity("item - " + i)); } else { list.add(new BEntity("item - " + i)); } } OnSelectedItemChanged listener = new OnSelectedItemChanged() { @Override public void onClick(int count) { Log.e("SelectedCount", count + ""); } }; adapter = new MutiTypeAdapter(getApplicationContext(), list, listener); lv.setAdapter(adapter); } }
OK,經過幾步就實現了所想要的功能!spa