您的位置:首页 > 移动开发 > Android开发

android ListView包含CheckBox时滑动丢失选中状态的解决

2015-02-03 14:22 639 查看


android ListView包含CheckBox时滑动丢失选中状态的解决


现象:listview 中,如果有10项,其中手机屏幕显示1-6项,其余的7-10项在屏幕中不可见,得向下滚动后才能看到,这个时候,如果选中1、2项,再滚动到7-10项,之后再滚动回来1-6项,就发现1、2项并未被选中。

我在进行android开发的过程中经常使用listview来显示数据,但是listview中的数据不是传统意义上的文字或图片,往往会有其他ui组件,而且还要根据需要为它们添加事件监听器,这个时候就需要自定义listview的适配器然后重载里面的getview()方法了。

Getview()方法是baseadapter里面一个重要的方法,它是在android显示listview里面的内容的时候回调的一个方法。下面就讲讲这个方法的工作机制(个人观点,如有不对,望指出)现在假设我们有10项内容要显示,但是一屏只能显示5项,那么android会首先创建6项对应的item的view的实例并缓存起来,当滑动屏幕,第一项还未移除屏幕,然后第6项已经进入了屏幕的时候,就会把多余的那个view实例用来显示第6项的内容,只有在第7项已经进入屏幕,但是第1项还未移除屏幕的时候才会新建一个view来显示同时缓存起来,此后就将移除屏幕的view用来显示新进入屏幕的item。其实有点类似于线程池的机制。这样的话我们的代码往往会这样写:

@Override

public View getView(int position, View convertView, ViewGroup parent) {

// TODO Auto-generated method stub

View view=null;

ViewHolder holder=null;

if(convertView==null){

convertView=LayoutInflater.from(context).inflate(R.layout.item, null);

holder=new ViewHolder();

holder.text=(TextView) convertView.findViewById(R.id.text);

holder.check=(CheckBox)convertView.findViewById(R.id.check);

convertView.setTag(holder);

}

else{

view =convertView;

holder=(ViewHolder)view.getTag();

}

holder.text.setText(list[position]);

return convertView;

}

其实这样可以大大的提高listview的效率,特别是当item项很多的时候,不用为每一个item新建一个view来显示,而只是固定数量的一些来循环的显示。

继续进行我们的研究,我们的目的是要为自己的 ui组件添加事件响应,但是这样又出先了一个问题,因为我们对ui组件的重用,这样一来 当屏幕滑动的时候ui组件就会相互重叠,比如的view里有一个checkbox当你选中以后,在滑动屏幕,可能在下面的莫一项上重用此组件的checkbox已被选上,这样就形成了干扰,下面的代码解决了这个问题,以checkbox为例:

package ld.test;

import java.util.HashMap;

import java.util.Map;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.TextView;

import android.widget.CompoundButton.OnCheckedChangeListener;

public class MyListAdapter extends BaseAdapter {

private Context context;

private String[] list;

private Map<Integer,Integer> selected;

public MyListAdapter(Context context,String[] list){

this.context=context;

this.list=list;

selected=new HashMap<Integer,Integer>();

}

private class ViewHolder{

TextView text;

CheckBox check;

}

@Override

public int getCount() {

// TODO Auto-generated method stub

return list.length;

}

@Override

public Object getItem(int position) {

// TODO Auto-generated method stub

return list[position];

}

@Override

public long getItemId(int position) {

// TODO Auto-generated method stub

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

// TODO Auto-generated method stub

View view=null;

ViewHolder holder=null;

if(convertView==null){

convertView=LayoutInflater.from(context).inflate(R.layout.item, null);

holder=new ViewHolder();

holder.text=(TextView) convertView.findViewById(R.id.text);

holder.check=(CheckBox)convertView.findViewById(R.id.check);

// holder.check.setTag(index);

convertView.setTag(holder);

}

else{

view =convertView;

holder=(ViewHolder)view.getTag();

}

holder.text.setText(list[position]);

holder.check.setTag(position);

if(selected.containsKey(position))

holder.check.setChecked(true);

else

holder.check.setChecked(false);

addListener(holder,position);//添加事件响应

return convertView;

}

private void addListener(ViewHolder holder,final int position){

holder.check.setOnCheckedChangeListener(new OnCheckedChangeListener(){

@Override

public void onCheckedChanged(CompoundButton buttonView,

boolean isChecked) {

// TODO Auto-generated method stub

if(isChecked){

if(!selected.containsKey(buttonView.getTag()))

selected.put((Integer)
buttonView.getTag(),position);

}

else{

selected.remove((Integer) buttonView.getTag());

}

}

});

}

}

这样一来无论你怎么滑动都不会相互干扰了。

效果图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐