滚动时,ArrayAdapter 顺序中的 ListView 混淆了
Posted
技术标签:
【中文标题】滚动时,ArrayAdapter 顺序中的 ListView 混淆了【英文标题】:ListView in ArrayAdapter order get's mixed up when scrolling 【发布时间】:2011-02-26 16:00:20 【问题描述】:我在自定义 ArrayAdapter 中有一个 ListView,它在每一行中显示一个图标 ImageView 和一个 TextView。当我使列表足够长以让您滚动浏览它时,顺序开始正确,但是当我开始向下滚动时,一些较早的条目开始重新出现。如果我向上滚动,旧的顺序会改变。重复执行此操作最终会导致整个列表顺序看似随机。所以滚动列表要么导致子顺序发生变化,要么绘图没有正确刷新。
什么会导致这样的事情发生?我需要将项目显示给用户的顺序与它们添加到 ArrayList 的顺序相同,或者至少保持一个静态顺序。如果我需要提供更详细的信息,请告诉我。任何帮助表示赞赏。谢谢。
【问题讨论】:
我有很长的列表要显示,我也遇到过 【参考方案1】:我遇到了类似的问题,但是当单击自定义列表中的项目时,屏幕上的项目会按顺序反转。如果我再次单击,它们会返回到原来的位置。
读完这篇文章后,我检查了我的代码,其中我重载了 getView 方法。我从convertedView 中获取视图,如果它为空,那么我将在那时构建我的东西。但是,在放置断点后,我发现它在每次点击时都会调用此方法,并且在随后的点击中,convertedView 不为空,因此没有设置项目。
这是一个例子:
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 非常感谢。 我想要你的孩子。感谢您完美简洁的解释。 嘿 Farcarts 你的回答对我有用,它对解决我的问题的各种帮助非常感谢。 天哪,你救了我的命。我要疯了,以为我从数据库中读取了不正确的数据,但实际上这只是我的 Listview 适配器在四处打乱。哇... -_____-....【参考方案2】:为了更一般的方式进一步阐明farcats的答案,以下是我的解释:
vi.inflate 操作(这里需要从 XML 解析行的布局并创建适当的 View 对象)由 if (view == null) 声明效率,因此同一对象的膨胀不会在每次出现时一次又一次地发生。
但是,getView 方法的其他部分用于设置其他参数,因此不应包含在 if (view == null) 语句中。
类似地,在此方法的其他常见实现中,一些 textView、ImageView 或 ImageButton 元素需要使用 list[position] 中的值填充,使用 findViewById 和之后的 .setText 或 .setImageBitmap 操作。 这些操作必须在都通过膨胀从头开始创建视图和如果不为空则获取现有视图之后进行。
另一个将此解决方案应用于 BaseAdapter 的好例子出现在 BaseAdapter causing ListView to go out of order when scrolled
【讨论】:
【参考方案3】:当您滚动时,ListView 会重用视图对象。您是否覆盖了 getView 方法?您需要确保为每个视图设置每个属性,不要假设它会记住您之前拥有的内容。如果您发布该方法,有人可能会指出您不正确的部分。
【讨论】:
【参考方案4】:我有一个 ListView、AdapterView 和一个包含 EditText 和 3 个 Spinner 的视图 (search_options)。 ListView 项目是 (search_options) 布局的多个副本,用户可以在 ListView 中添加更多选项,然后单击搜索发送根据用户选项构建的 sql 查询。
我发现 convertView 混合不合理,所以我在活动中添加了一个全局列表 (myViews) 并将其传递给 ArrayAdapter。然后在 ArrayAdapter (getView) 中添加每个新添加的视图 (myViews)。
同样在 getView 上,而不是检查 convertView 是否为空,我检查全局列表 (myViews) 是否对选定的(位置)有视图。它在失去 3 天阅读互联网后完全解决了问题!!
1-在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;
终于不用再混东西了……
【讨论】:
非常感谢您的回答!你帮了我很多!以上是关于滚动时,ArrayAdapter 顺序中的 ListView 混淆了的主要内容,如果未能解决你的问题,请参考以下文章
Android View 不会通过滑动手势滚动,也不会滚动。将 ListView 与 ArrayAdapter 一起使用
如何实现 Asynctask 在 ArrayAdapter 中加载图像
ListView ArrayAdapter,将子项隐藏在 Row 中?
当 ArrayAdapter.isEnabled 返回 false 时,ListView 中的分隔符消失