ListView getChildAt为可见子项返回null

时间:2011-07-20 18:26:23

标签: android listview null

我从listview / getChildAt方法中获得了一些奇怪的行为。

我有一个HashSet,iconsToUpdate,已在数据库中更改过的图标。我想迭代可见行,看看是否需要更新任何图标以反映新图标。我不需要测试当前不在视图中的图标,因为它们在渲染时会被正确绘制。

我的问题是getChildAt在看起来不应该返回null。我知道getChildAt只能返回当前可见的视图,但是对于某些可见的行,它返回null。

这是我的代码,它迭代可见的行:

Logger.debug("First visible index: " + f_listView.getFirstVisiblePosition());
Logger.debug("Last visible index: " + f_listView.getLastVisiblePosition());
for (int i = f_listView.getFirstVisiblePosition(); i <= f_listView.getLastVisiblePosition(); i++) {
    String tag = "asdf"; // Remove when bug is fixed.
    if (f_listView == null) {
        Logger.debug("f_listView is null");
    } else if (f_listView.getChildAt(i) == null) {
        Logger.debug("Child at index " + i + " is null");
    } else {
        tag = (String) f_listView.getChildAt(i).getTag();
        Logger.debug("Successful at index " + i + ", tag is: " + tag);
    }
    if (iconsToUpdate.contains(tag)) {
        setIcon(i, f_aim.getInHouseIcon(tag));
    }
}

这是与此循环运行相对应的日志:

D/...: First visible index: 3
D/...: Last visible index: 8
D/...: Successful at index 3, tag is: ...
D/...: Successful at index 4, tag is: ...
D/...: Successful at index 5, tag is: ...
D/...: Child at index 6 is null
D/...: Child at index 7 is null
D/...: Child at index 8 is null

应该注意的是,正确报告了第一个和最后一个可见索引,因为我在运行它时正在查看第3-8行。第6,7,8行正确呈现。如果它们为空,它们是如何显示的?

此外,我不知道这是否重要,但当我位于列表视图的顶部时,第5行是最后一行。

关于为什么将这些行返回为null的任何信息都将非常感激。

谢谢!

6 个答案:

答案 0 :(得分:134)

listView.getChildAt(i)的工作原理,其中0是第一个可见行,(n-1)是最后一个可见行(其中n是您看到的可见视图数)。

get last / first visible返回您拥有的dataAdapter中的位置。所以你从第3个位置开始,看起来像是6个可见的视图,那么当获得6-8个位置时,你就会得到null。

在你的例子中,getChildAt(0)将返回位置3.我通常做的是将位置存储在我的视图中,这样如果我需要值,我可以在以后查找我的dataAdapter。

我认为你的for循环应该是这样的:

for (int i = 0; i <= f_listView.getLastVisiblePosition() - f_listView.getFirstVisiblePosition(); i++) 

希望这有帮助。

答案 1 :(得分:3)

当您致电listView1.getLastVisiblePosition()listView1.getFirstVisiblePosition()时,listview会返回列表视图中部分可见的项目的位置。例如,第一项可以是一半可见,最后一项可以是一半可见。在这种情况下,即使您可以在列表视图中看到项目的一部分,适配器尚未调用该项目的getView()函数,因此该项目仍被视为空。

答案 2 :(得分:0)

他们可能部分可见。但是当getView()尝试回收视图时,它会获得完全可见的视图,而其他视图则将它们视为null。例如,如果您滚动列表并且顶部项目部分可见且底部部分可见,那么这些是空值但您仍然可以看到它们。

答案 3 :(得分:0)

  

我在OnListItemClickListener()中尝试过,但是失败了。最后我在listview的定制适配器上做了一些修改。在getView()中,我将clickListener应用于我经常添加到列表中的项目。那里做所有必需的功能。这是我的代码,我在列表中添加了Image View,因此在imageview上应用了listener。

     

我认为它会帮助那些想要在选择特定列表项时更改颜色的人。去吧..

在自定义适配器的getView()中 // - - - - - - - - - - - - - - - - -码 - - - - - - - ----------------------------

LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View rowView = inflater.inflate(R.layout.icon_image_layout, parent, false); ImageView imageView = (ImageView) rowView.findViewById(R.id.Icon_ImageView); imageView.setClickable(true); final int pos=position; imageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub // TODO Auto-generated method stub try{ if(previous_view!=null) previous_view.setBackgroundColor(Color.WHITE); }catch (Exception e) { System.out.println("Exception Occurs Previous View"); } v.setBackgroundColor(Color.RED); MainActivity.imageView.setImageResource(MainActivity.Image_Name[pos]); previous_view=v; return false; } });

答案 4 :(得分:0)

我知道这是很老的帖子。但我正在回答,因为人们仍然在寻找ListView getChildAt()空指针异常的解决方法。

这是因为ArrayApdater因为高度而正在REMOVING和RECYCLING ListView上尚未显示的视图。因此,如果您有10个项目视图,并且ListView可以在当时显示4 - 5:

适配器删除位置5到9的项目视图,这样任何adapter.getChildAt(5... to 9)的尝试都会导致空指针异常

适配器还可以循环显示项目视图,这样当您向下滚动到5到9时,您在位置3上所做的任何引用都会丢失,以及您在第3个位置上进行的任何输入(EditText,Checkbox等) 。)当你向下滚动到5到9时将被回收,并且将在以后的另一个位置(从位置1,2或3等)重新使用具有相同值的

我发现控制它的唯一方法是忘记获取视图并拥有:

属性HashMap<Integer, ImageView> iconViews或您希望处理要用于列表中每个项目的值的任何类型。对于item->getId()position等项,第一种类型必须是唯一的。在构造函数中使用new HashMap<>()初始化它; 在getViews中iconViews.put(position, iconView); 阻止适配器使用回收的convertView,删除条件if(convertView == null),以便适配器始终为全新的视图实例充气。因为视图实例每次都是新的,所以每次都必须从HashMap设置值,就好像它已经包含键if(iconViews.containsKey(position)){iconView = iconViews.get(position))};一样。可能在这种情况下,没有大量的项目,所以平滑滚动不是必须的。

最后创建公共方法以获取Adapter之外的值传递item->getId() Integer作为参数。例如:public ImageView getIconViewAt(int position) { return iconViews.get(position); }。然后,从适配器

中选择项目将很容易

请参阅我的answer

答案 5 :(得分:-1)

不是因为你在说

f_listView.getChildAt(i) 

你应该在那个位置检索项目吗?

f_listView.getItemAtPosition(i)