ArrayAdapter中的ListView顺序在滚动时混淆了

时间:2010-06-02 05:29:59

标签: android listview android-arrayadapter

我在自定义ArrayAdapter中有一个ListView,它在每行中显示一个图标ImageView和一个TextView。当我使列表足够长以允许您滚动它时,顺序开始正确,但是当我开始向下滚动时,一些较早的条目开始重新出现。如果我向上滚动,旧订单会更改。反复执行此操作最终会导致整个列表顺序看似随机。因此滚动列表要么导致子顺序改变,要么绘图没有正确刷新。

什么可能导致这样的事情发生?我需要将项目显示给用户的顺序与它们添加到ArrayList的顺序相同,或者至少保持一个静态顺序。如果我需要提供更详细的信息,请告诉我。任何帮助表示赞赏。感谢。

4 个答案:

答案 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;
}

最后没有更多的混合物......