在发帖时,可以从手机相册选择图片,最多可以选择9张。要实现的效果如图所示:
单击右上角的勾勾选择图片或者取消选择。
一开始我的实现逻辑是这样的:
1、在adapter里面的绑定ViewHolder时,设置勾勾的点击事件:
vh.hookImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hookClickListener != null) {
hookClickListener.onChange(position, v);
}
}
});
回调接口:
public interface HookClickListener {
void onChange(int position, View v);
}
2、在activity里面设置上述回调监听,并实现:
private MultiSelectPhotoAdapter.HookClickListener hookClickListener = new MultiSelectPhotoAdapter.HookClickListener() {
@Override
public void onChange(int position, View v) {
if (!v.isSelected()) {
if (selectPhotos.size() >= maxNum) {
showToast(R.string.photo_over_tip);
return;
}
selectPhotos.add(mPhotoAdapter.data.get(position));
} else {
selectPhotos.remove(mPhotoAdapter.data.get(position));
}
v.setSelected(!v.isSelected());
}
};
当没有选中时,先看是否已经选择了9张图片,则提示“最多只能选择9张图片”,没有选中9张,则增加到选中列表;反之,从选中列表中remove掉。设置select状态。这样做有很大的问题,点击右上角的勾勾时,经常选不上或者错乱。后来我分析,应该是ItemView复用导致的,view与position已经不对应了。
改良型代码如下,完美解决上述问题:
1、在adapter里面增加一个列表专门存放select状态:
private SparseBooleanArray selectArray;
public MultiSelectPhotoAdapter(List<String> data, Context context, int itemSize) {
super(data, context);
this.itemSize = itemSize;
selectArray = new SparseBooleanArray(data.size());
}
用SparseBooleanArray因为它的效率比较高,android做过优化,比HashMap效率高,它采用折半查找。
封装使用SparseBooleanArray的getter和setter方法:
public boolean getSelect(int position) {
return selectArray.get(position, false);
}
public void setSelect(int position, boolean b) {
selectArray.put(position, b);
notifyDataSetChanged();
}
在设置select状态时,通知adapter变更,重新绘制。
2、下面这两步和上面类似,只是实现方法有所改变。在adapter里面的绑定ViewHolder时,设置勾勾的点击事件:
viewHolder.hookImageView.setSelected(getSelect(position)); // --------------1
viewHolder.hookImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hookClickListener != null) {
hookClickListener.onChange(position);
}
}
});
可以看到在1的地方多了一句,这里就是重点,把勾勾的select状态与SparseBooleanArray绑定在了一起,当SparseBooleanArray中的select状态改变时,调用notifyDataSetChanged()方法重绘ItemView的选中状态。
回调接口:
public interface HookClickListener {
void onChange(int position);
}
2、在activity里面设置上述回调监听,并实现:
private MultiSelectPhotoAdapter.HookClickListener hookClickListener = new MultiSelectPhotoAdapter.HookClickListener() {
@Override
public void onChange(int position) {
if (!mPhotoAdapter.getSelect(position)) {
if (selectPhotos.size() >= maxNum) {
showToast(R.string.photo_over_tip);
return;
}
selectPhotos.add(mPhotoAdapter.data.get(position));
} else {
selectPhotos.remove(mPhotoAdapter.data.get(position));
}
mPhotoAdapter.setSelect(position, !mPhotoAdapter.getSelect(position));
}
};
参考: