我在自定义ArrayAdapter中有一个ListView,它在每行中显示一个图标ImageView和一个TextView。当我使列表足够长以允许您滚动它时,顺序开始正确,但是当我开始向下滚动时,一些较早的条目开始重新出现。如果我向上滚动,旧订单会更改。反复执行此操作最终会导致整个列表顺序看似随机。因此滚动列表要么导致子顺序改变,要么绘图没有正确刷新。
什么可能导致这样的事情发生?我需要将项目显示给用户的顺序与它们添加到ArrayList的顺序相同,或者至少保持一个静态顺序。如果我需要提供更详细的信息,请告诉我。任何帮助表示赞赏。感谢。
答案 0 :(得分:57)
我遇到了类似的问题,但是当点击自定义列表中的某个项目时,屏幕上的项目会按顺序反转。如果我再次点击,他们会回到原来的位置。
阅读完之后,我检查了我的代码,我在那里重载了getView方法。我从convertView获取视图,如果它是null,那就是我构建我的东西的时候。但是,在放置断点之后,我发现它在每次点击和后续点击时调用此方法,convertView不为null,因此没有设置项目。
这是一个例子:
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listitemrow, null);
RssItem rssItem = (RssItem) super.getItem(position);
if (rssItem != null)
{
TextView title = (TextView) view.findViewById(R.id.rowtitle);
if (title != null)
{
title.setText(rssItem.getTitle());
}
}
}
return view;
}
微妙的变化是将视图上的空检查的近括号移动到膨胀之后:
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listitemrow, null);
}
RssItem rssItem = (RssItem) super.getItem(position);
if (rssItem != null)
{
TextView title = (TextView) view.findViewById(R.id.rowtitle);
if (title != null)
{
title.setText(rssItem.getTitle());
}
}
return view;
}
我希望这可以帮助那些遇到同样问题的人。
答案 1 :(得分:4)
为了进一步澄清以下 farcats 的答案,我的解释如下:
vi.inflate 操作(这里需要从XML解析行的布局并创建适当的View对象)由 if(view == null)<包装/ em>效率声明,因此每次弹出视图时,同一物体的膨胀不会一次又一次地发生。
但是,getView方法的其他部分用于设置其他参数,因此不应包含在 if(view == null)语句中。
类似地,在此方法的其他常见实现中,某些textView,ImageView或ImageButton元素需要使用 findViewById 以及之后的 .setText来填充list [position]中的值。 或 .setImageBitmap 操作。 这些操作必须在两者之后通过通货膨胀从创建一个视图,如果不是null,则获取现有视图。
将此解决方案应用于BaseAdapter的另一个好例子显示在BaseAdapter causing ListView to go out of order when scrolled
中答案 2 :(得分:3)
滚动时ListView重用视图对象。你是否重写了getView方法?您需要确保为每个视图设置每个属性,不要认为它会记住您之前的内容。如果您发布该方法,有人可能会指出您不正确的部分。
答案 3 :(得分:0)
我有一个ListView,AdapterView和一个包含EditText和3个Spinners的View(search_options)。 ListView项目是(search_options)布局的多个副本,其中用户可以在ListView中添加更多选项,然后单击搜索以发送根据用户选项构建的sql查询。
我发现convertView混合indecies所以我在activity中添加了一个全局列表(myViews)并将其传递给ArrayAdapter。然后在ArrayAdapter(getView)中,我将每个新添加的视图添加到它(myViews)。
同样在getView上,而不是检查convertView是否为null,我检查全局列表(myViews)是否有一个关于所选(位置)的视图..它完全解决了丢失3天阅读互联网后的问题!!
1- on Activity添加:
Map<Integer, View> myViews = new HashMap<>();
然后使用适配器构造函数将其传递给ArrayAdapter。
mSOAdapter = new SearchOptionsAdapter(getActivity(), resultStrs, myViews);
2-在getView上:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder viewHolder;
if (!myViews.containsKey(position)) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
view = inflater.inflate(R.layout.search_options, parent, false);
/// ...... YOUR CODE
myViews.put(position, view);
FontUtils.setCustomFontsIn(view, getContext().getAssets());
}else {
view = myViews.get(position);
}
return view;
}
最后没有更多的混合物......