繁体   English   中英

滚动时ArrayAdapter中的ListView顺序混乱

[英]ListView in ArrayAdapter order get's mixed up when scrolling

我在自定义ArrayAdapter中有一个ListView,该数组在每行中显示一个ImageImageView和一个TextView。 当我使列表足够长以使您可以滚动列表时,该顺序从右开始,但是当我开始向下滚动时,一些较早的条目开始重新出现。 如果我向上滚动,旧的顺序会改变。 重复执行此操作最终会导致整个列表顺序看似随机。 因此,滚动列表会导致子顺序更改,或者图形无法正确刷新。

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

我遇到了类似的问题,但是单击自定义列表中的项目时,屏幕上的项目将依次颠倒。 如果我再次单击,它们会退回到原来的位置。

阅读此内容后,我检查了我的代码,在其中我重载了getView方法。 我是从convertedView获取视图的,如果它为null,那就是在构建自己的东西时。 但是,在放置断点后,我发现它在每次单击以及随后的单击时都调用此方法,convertedView不为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;
}

希望这对遇到同样问题的其他人有所帮助。

为了以更一般的方式进一步阐明以下Farcat的答案,以下是我的解释:

vi.inflate操作(此处是从XML解析行的布局并创建适当的View对象所需的操作)由if(view == null)语句包装,以提高效率,因此不会发生同一对象的膨胀一次又一次地出现在视图中。

但是,getView方法的其他部分用于设置其他参数,因此不应包含在if(view == null)语句中。

相若方式,在其他常见的实现该方法,一些TextView的的,ImageView的或ImageButton的元件需要由值从列表[位置]填充,使用findViewById并且之后.setText.setImageBitmap操作。 这些操作必须来受通胀从头开始创建一个视图,并让现有视图如果不为空后。

另一个适用于BaseAdapter的解决方案的好示例出现在BaseAdapter中,导致滚动时ListView出现故障

滚动时,ListView重用视图对象。 您要覆盖getView方法吗? 您需要确保为每个视图都设置了每个属性,不要以为它会记住您以前拥有的内容。 如果您发布该方法,则有人可能会指出您不正确的部分。

我有一个ListView,AdapterView和一个包含EditText和3 Spinners的视图(search_options)。 ListView项目是(search_options)布局的多个副本,用户可以在ListView中添加更多选项,然后单击“搜索”以发送根据用户选项构建的sql查询。

我发现convertView的混合效果不确定,因此我在活动中添加了一个全局列表(myViews),并将其传递给ArrayAdapter。 然后在ArrayAdapter(getView)中,将每个新添加的视图添加到其中(myViews)。

同样在getView上,而不是检查convertView是否为null,我检查全局列表(myViews)是否具有选定位置(位置)上的视图。在丢失三天的互联网阅读时间后,它完全解决了问题!

1-在活动上添加以下内容:

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

终于没有更多的混合项目了...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM