我有一个使用自定义ArrayAdapter的列表视图。 ListView的项目是RelativeLayouts。存储在“Track”对象的“lightsOnThisTrack”列表中的“Light”视图随后被添加到其相应的RelativeLayouts中。在ListView中添加视图到RelativeLayout产生重复的项目
问题是,如果我向ListView添加更多项目,以前添加到relativeLayouts的视图开始在新添加的项目上重复。另一方面,TextView“trackText”没有被重复,正如在示例中可以看到的那样。正如我在其他帖子上看到的,我知道这是与ViewHolder模式实现方式有关的问题,但我无法找到问题所在。
public class TrackListAdapter extends ArrayAdapter<Track> {
private static final String TAG = "TrackListAdapter";
private LayoutInflater layoutInflater;
public ArrayList<Track> trackArrayList;
Context mContext;
RelativeLayout relativeLayout;
public TrackListAdapter(Context context, ArrayList<Track> trackArrayList) {
super(context, 0, trackArrayList);
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mContext = context;
this.trackArrayList = trackArrayList;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ViewHolder viewHolder;
if (rowView == null) {
rowView = layoutInflater.inflate(R.layout.track_list_item, null);
viewHolder = new ViewHolder();
viewHolder.relativeLayout = (RelativeLayout) rowView.findViewById(R.id.relativeLayout);
viewHolder.trackText = new TextView(mContext);
viewHolder.trackText.setTextColor(Color.GRAY);
viewHolder.trackText.setX(100);
viewHolder.trackText.setY(20);
viewHolder.trackText.setTextSize(18);
viewHolder.relativeLayout.addView(viewHolder.trackText);
rowView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.track = trackArrayList.get(position);
if (viewHolder.track.getName() == null)
viewHolder.trackText.setText(" NUMBER " + position);
else
viewHolder.trackText.setText(viewHolder.track.getName());
for (int i = 0; i < viewHolder.track.getNumberOfLights(); i++) {
Light light = viewHolder.track.lightsOnThisTrackList.get(i);
if (light.getParent() != null) {
if (!light.getParent().equals(viewHolder.relativeLayout)) {
ViewGroup viewGroup = (ViewGroup) light.getParent();
if (viewGroup != null) viewGroup.removeView(light);
viewHolder.relativeLayout.addView(light);
}
} else {
viewHolder.relativeLayout.addView(light);
}
}
notifyDataSetInvalidated();
notifyDataSetChanged();
return rowView;
}
public static class ViewHolder {
Track track;
TextView trackText;
RelativeLayout relativeLayout;
}
public View getViewByPosition(int pos, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition) {
return listView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
}
谢谢,删除RelativeLayout中的前视图做了诀窍。另外,正如你设想的那样,'notifyDataSetInvalidated()'和'notifyDataSetChanged()'在getView()内部是不必要的,只需将它放在我修改数据集的代码部分即可。 – gotramaval
最后,我在listView中使用这些视图,因为我希望能够滚动它们而不必编码视图的滚动。那么你会如何提出这样做?(我真的不能预见'Track'上会有'Light'的最大数量,并且它们没有特定的位置,因为用户可以沿轨道图像拖动它们) – gotramaval
@gotramaval I don不知道什么对你的用例最好,但是我认为如果你打算让这些灯可以拖动,那么'ListView'会让你的生活变得非常困难。对于触摸交互控制,“ListView”相当沉重。如果您可以切换到使用'RecyclerView',那会更好。 – Karakuri