使用带有扩展 BaseAdapter 的 GridView 我正在加载包含图像和标题的 RelativeLayouts 集合。当用户单击 GridView 中的这些项目之一时,它应该从网格中删除并替换为它后面的项目。
这适用于除第一个项目以外的任何项目(适配器管理的项目的 ArrayList 中的索引 0)。
在我正在测试的设备上,当屏幕完全滚动到网格顶部(3 列和 4 行)并且最后一行被稍微切断时,屏幕能够显示 12 个项目。第 5 行根本没有显示。在这种情况下,如果我单击第一项(将其删除),则所有项都正确填写,但是,第 5 行的第一项(索引 12)返回第一项(索引 0)的视图索引 12 处的项目。
一些有助于解释问题的屏幕:
点击 Brian McKnight 将删除他,然后 BECK 和其他人将填补。
BECK 已与其余部分一起填写,现在向下滚动到下一行。
哦哦。贝克也在那儿。我让它部分滚动,所以你可以看到这两个项目都有 BECK 图片。
向上滚动以使第 12 项(第 5 行)不在视线范围内,然后向下滚动可纠正问题。
网格中任何其他项目的此过程都正常工作,只是项目 0。我做了一些日志记录并发现了一些事情:
- 对象 0 的 getView(...) 方法被调用了很多。当网格第一次加载时,它被调用了 3 次,而所有其他项只被调用一次。
- 当项目 0 以外的项目被删除时,位置 0 的 getView(...) 被调用 19 次。一开始是 3 次,然后在调用了其他对象的所有 getView(...) 方法之后再进行 16 次。
- 当项目 0 被删除时,在您向下滚动到第 5 行(项目 12)之后,将调用 0 的 getView(...) 方法两次。我认为问题出在此处,因为有时如果您可以看到正确的项目在被@位置 0 的项目覆盖之前开始加载。
所以我很确定位置 0 的额外 2 次 getView(...) 调用(在 item @ index 12 出现时调用)是导致此问题的原因。我不知道为什么当时会调用位置 0 的 getView(...) ,以及为什么它会决定覆盖@位置 12 的项目。
我将在下面包含我的适配器的代码,我认为这足以解决问题。
public class PopularArtistsGridAdapter extends BaseAdapter {
private ArrayList<ArtistsListItem> mArtists = new ArrayList<ArtistsListItem>();
private LayoutInflater mInflater;
private Context mContext;
private int mRemovedIndex = -1;
private int mRefresher = -1;
private int mLastVisible = -1;
public PopularArtistsGridAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setItems(ArrayList<ArtistsListItem> artists) {
if(artists == null)
throw new NullPointerException();
mArtists = artists;
notifyDataSetChanged();
}
@Override
public int getCount() {
return mArtists.size();
}
public void removeItem(int position, int lastVisible) {
mLastVisible = lastVisible;
mRemovedIndex = position;
mRefresher = mRemovedIndex;
mArtists.remove(position);
notifyDataSetChanged();
}
public void addItem(int position) {
ArtistsListItem item = getItem(position);
mArtists.add(0, item);
notifyDataSetChanged();
}
@Override
public ArtistsListItem getItem(int position) {
return mArtists.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private void iterateRefresher() {
mRefresher++;
if(mRefresher > mLastVisible) {
mRemovedIndex = -1;
mRefresher = -1;
mLastVisible = -1;
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ArtistsListItem item = getItem(position);
if(convertView == null)
convertView = mInflater.inflate(R.layout.popular_artist_item, null);
final TextView tv = (TextView) convertView.findViewById(R.id.pai_stupid_bubble_button);
final ImageView iv = (ImageView) convertView.findViewById(R.id.pai_image);
final BitmapDrawable drawable = DrawableManager.fetchBitmapDrawable(mContext, item.getImageURL(), true, false);
iv.invalidate();
tv.invalidate();
if(mRefresher >= 0 && position >= mRefresher) {
Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.grid_item_fadein);
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
iv.setImageDrawable(drawable);
tv.setText(item.getName());
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
}
});
anim.setStartOffset(300 + (50 * (position - mRemovedIndex)));
convertView.startAnimation(anim);
iterateRefresher();
}
else {
iv.setImageDrawable(drawable);
tv.setText(item.getName());
}
return convertView;
}
}
复习是我为了让屏幕上的所有可见项目在替换已删除项目时淡入淡出而制作的。如果有人在这里看到任何可疑的东西,或者对为什么会发生这种情况有任何其他想法,我将不胜感激。谢谢!