我正在尝试制作一个充满复选框的GridView。我遵循ViewHolder模式来回收视图并尝试将复选框设置为正确的值,但由于某种原因,我似乎无法使它们不重复。 在我的调试工作之后,我发现我的SparseBooleanArray正在被正确更新 - 只是将它应用到视图似乎打开了错误的复选框,即使我将它们应用到正确的位置。 这是我的GridView的整个适配器 - 相关部分是getView和onCheckedChanged
// Our image adapter takes our list of thumbnails and creates a selectable grid full of asychroniously loaded images.
public class ThumbnailImageAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener {
Context mContext;
LayoutInflater mInflater;
SparseBooleanArray mCheckedStates;
private int mItemHeight = 0;
private int mNumColumns = 0;
private RelativeLayout.LayoutParams mImageViewLayoutParams;
private ArrayList<String> mList;
private ArrayList<String> mImageFullResUrls;
private String nextURL;
public ThumbnailImageAdapter(Context context) {
super();
mContext = context;
mInflater = LayoutInflater.from(mContext);
mImageViewLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
clear();
}
public ArrayList<String> getCheckedItems() {
ArrayList<String> checkedItems = new ArrayList<String>();
for (int i = 0; i < mList.size(); i++) {
if (mCheckedStates.get(i)) {
checkedItems.add(mImageFullResUrls.get(i));
}
}
return checkedItems;
}
public boolean hasSelectedItems() {
return mCheckedStates.indexOfValue(true) >= 0;
}
@Override
public int getCount() {
// If columns have yet to be determined, return no items
if (getNumColumns() == 0) {
return 0;
}
return mList.size();
}
@Override
public Object getItem(int position) {
return mImageFullResUrls.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup container) {
if(position >= getCount()) {
return null;
}
final ThumbnailViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.selectable_imageview, null);
holder = new ThumbnailViewHolder();
holder.checkbox = (CheckBox) convertView.findViewById(R.id.photo_checkbox);
holder.imageView = (SmartImageView) convertView.findViewById(R.id.photo_imageview);
convertView.setTag(holder);
} else {
holder = (ThumbnailViewHolder) convertView.getTag();
}
holder.checkbox.setTag(position);
holder.checkbox.setOnCheckedChangeListener(this);
holder.checkbox.setChecked(mCheckedStates.get(position, false));
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
holder.imageView.setImageUrl(mList.get(position));
final View finalView = convertView;
convertView.post(new Runnable() {
@Override
public void run() {
Rect delegateArea = new Rect();
holder.imageView.getHitRect(delegateArea);
finalView.setTouchDelegate(new TouchDelegate(delegateArea, holder.checkbox));
}
});
return convertView;
}
public void setItemHeight(int height) {
if (height == mItemHeight) {
return;
}
mItemHeight = height;
mImageViewLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, mItemHeight);
notifyDataSetChanged();
}
public int getNumColumns() {
return mNumColumns;
}
public void setNumColumns(int numColumns) {
mNumColumns = numColumns;
}
public void appendImage(String thumbUrl, String fullResUrl) {
if (!mList.contains(thumbUrl)) {
mList.add(thumbUrl);
mImageFullResUrls.add(fullResUrl);
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}
}
public void prependImage(String thumbUrl, String fullResUrl) {
if (!mList.contains(thumbUrl)) {
mList.add(0, thumbUrl);
mImageFullResUrls.add(0, fullResUrl);
SparseBooleanArray shiftedArray = new SparseBooleanArray(mList.size());
// Shift our entire array one down (there has to be a better way to do this)
for (int i = 0; i < mCheckedStates.size(); i++) {
shiftedArray.put(mCheckedStates.keyAt(i) + 1, mCheckedStates.valueAt(i));
}
mCheckedStates = shiftedArray;
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}
public void clear() {
mList = new ArrayList<String>();
mImageFullResUrls = new ArrayList<String>();
mCheckedStates = new SparseBooleanArray();
}
public String getNextURL() {
return this.nextURL;
}
public void setNextURL(String nextURL) {
this.nextURL = nextURL;
}
public ArrayList<String> getThumbnailURLs() {
return mList;
}
@Override
public void onCheckedChanged(CompoundButton checkBoxView, boolean isChecked) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
final int numPhotos = Integer.parseInt(settings.getString("num_photos", null));
if (mAdapter.getCheckedItems().size() > numPhotos) {
checkBoxView.setChecked(false); // Don't allow the user to select more than numPhotos photos
}
// This animates our image "pressed" and "unpressed" states
mCheckedStates.put((Integer) checkBoxView.getTag(), isChecked);
final ImageView image = (ImageView) ((ViewGroup) checkBoxView.getParent()).findViewById(R.id.photo_imageview);
int dpi = getResources().getDisplayMetrics().densityDpi;
int _12dp = (int) (12 * (dpi / 160f));
ValueAnimator animator;
if (isChecked) {
animator = ValueAnimator.ofInt(image.getPaddingRight(), _12dp);
} else {
animator = ValueAnimator.ofInt(image.getPaddingRight(), 0);
}
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int v = (Integer) valueAnimator.getAnimatedValue();
image.setPadding(v, v, v, v);
}
});
animator.setDuration(100);
animator.start();
mOnImageSelectionChangeListener.onImageSelectionChange(getCheckedItems());
getActivity().invalidateOptionsMenu();
}
}
static class ThumbnailViewHolder {
CheckBox checkbox;
SmartImageView imageView;
}
答案 0 :(得分:0)
这是由于网格视图回收视图的方式。
为您的适配器实施以下内容
implements CompoundButton.OnCheckedChangeListener
然后有一个SpareBooleanArray来跟踪已检查的陈述
SparseBooleanArray mCheckStates;
然后
mCheckStates = new SparseBooleanArray(your data size);
在getView中
holder.chkSelect.setTag(position);
holder.chkSelect.setChecked(mCheckStates.get(position, false));
holder.chkSelect.setOnCheckedChangeListener(this);
然后覆盖
public boolean isChecked(int position) {
return mCheckStates.get(position, false);
}
public void setChecked(int position, boolean isChecked) {
mCheckStates.put(position, isChecked);
}
public void toggle(int position) {
setChecked(position, !isChecked(position));
}
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mCheckStates.put((Integer) buttonView.getTag(), isChecked);
}
同时移动此
holder.imageView = (SmartImageView) convertView.findViewById(R.id.photo_imageview);
到getView的if部分
并更改此
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
imageView.setImageUrl(mList.get(position));
到
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setLayoutParams(mImageViewLayoutParams);
// Finally load the image asynchronously into the ImageView, this also takes care of
// setting a placeholder image while the background thread runs
holder.imageView.setImageUrl(mList.get(position));
你可以找到一个类似的例子@