在ListView的使用过程中,我们经常会用到View的复用机制,来优化应用的性能。也就是说ListView的item的View存在着复用,刚开始Adapter会创造一个屏幕的item,以后的Item就会复用这最初的Item View,只不过把数据更换了而已。于是这样便会带来一个问题,加入Item上有一些局部事件,比如说ChexkBox,当我们点击的是第一项的时候,第一个Item的CheckBoX的选中状态确实改变了,但是继续往下拉,你会发现,下面还有CheckBox的选中状态改变了。因为下面的Item复用了初始的Item View,所以会造成点击,改变状态或者Button上的文字时,会发生错乱。
如何解决这个问题呢?解决的方法有两个。第一是定义一个List<Integer>集合,用来存放被点击的position。第二个方法是,在你的Item的内容的Bean中添加一个字段boolean isClicked,用来标记是否被点击过了。
首先来介绍方法一:刚开始的时候,判断集合是否存在这个position,如果存在则,将内容设置为点击状态。否则,设置为正常状态。接着是点击事件的处理:如果集合已经存在了这个position,那么说明前面已经被点击过一次了,那么这次恢复正常的状态,并且将position从集合中移除。如果集合不存在该positon,则说明这是第一次点击,那么将它处理成点击的状态,并且将position添加到集合中去。
说完了,该上代码了
public class TestActivity extends Activity {
private ListView listView;
private TestAdapter adapter;
//定义一个集合用来保存被点击的position
private List<Integer> clickList = new ArrayList<Integer>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
listView = (ListView) findViewById(R.id.list);
adapter = new TestAdapter();
listView.setAdapter(adapter);
}
class TestAdapter extends BaseAdapter {
@Override
public int getCount() {
return 22;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView,ViewGroup parent) {
final ViewHolder holder;
if (null == convertView) {
holder = new ViewHolder();
convertView = LayoutInflater.from(TestActivity.this).inflate(R.layout.item_list, parent, false);
holder.button = (Button) convertView.findViewById(R.id.btn);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (clickList.contains(Integer.valueOf(position))) {
holder.button.setText("我是第" + position);
} else {
holder.button.setText("点击我吧");
}
holder.button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (clickList.contains(position)) {
clickList.remove(Integer.valueOf(position));
holder.button.setText("点击我吧");
} else {
clickList.add(position);
holder.button.setText("我是第" + position);
}
}
});
return convertView;
}
}
class ViewHolder {
Button button;
}
}
至于第二个方法,不过是变换了一种形式,其实和第一种方法是一样的意思。
只是展示方法的使用,所以只用了一个成员
public class Click {
private boolean isClicked = false;
public boolean isClicked() {
return isClicked;
}
public void setClicked(boolean isClicked) {
this.isClicked = isClicked;
}
}
继续上代码
public class TestActivity extends Activity {
private ListView listView;
private TestAdapter adapter;
//ListView的数据源
private List<Click> beanList = new ArrayList<Click>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
//添加22项数据
for(int i=0; i<22; i++){
beanList.add(new Click());
}
listView = (ListView) findViewById(R.id.list);
adapter = new TestAdapter();
listView.setAdapter(adapter);
}
class TestAdapter extends BaseAdapter {
@Override
public int getCount() {
return beanList.size();
}
@Override
public Object getItem(int position) {
return beanList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView,ViewGroup parent) {
final ViewHolder holder;
if (null == convertView) {
holder = new ViewHolder();
convertView = LayoutInflater.from(TestActivity.this).inflate(R.layout.item_list, parent, false);
holder.button = (Button) convertView.findViewById(R.id.btn);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//判断初始状态,并作相应的内容处理
Click bean = beanList.get(position);
if (bean.isClicked()) {
holder.button.setText("我是第" + position);
} else {
holder.button.setText("点击我吧");
}
holder.button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//原来是isClicked,即被点击过了,则更改isClicked为false
if (beanList.get(position).isClicked()) {
beanList.get(position).setClicked(false);
holder.button.setText("点击我吧");
} else {
beanList.get(position).setClicked(true);
holder.button.setText("我是第" + position);
}
}
});
return convertView;
}
}
class ViewHolder {
Button button;
}
}
效果图