【问题标题】:Sometimes listView.getChildAt(int index) returns NULL (Android)有时 listView.getChildAt(int index) 返回 NULL (Android)
【发布时间】:2012-04-25 15:31:58
【问题描述】:

我有一个带有自定义适配器的 listView。当发生某些事情时(点击孩子),我会做一些计算并修改子视图。如果满足某些条件,则应修改与单击的孩子无关的其他孩子。

这有时有效,但有时会失败,并且 DDMS 说视图为空...

让我给你看代码:

        if(invalidaEste != -1)
        {
            try
            {
                View v = lv_data.getChildAt(invalidaEste);
                if( v== null)
                {
                    Log.e("MY_LOG", "SIZE " + lv_data.getCount());
                    Log.e("MY_LOG", "IS_NULL " + String.valueOf(invalidaEste)); 
                }

                if(invalidaEste >= lv_data.getFirstVisiblePosition() &&
                   invalidaEste <= lv_data.getLastVisiblePosition())
                {
                    RelacionFacturaPago rpf = (RelacionFacturaPago)lv_data.getAdapter().getItem(invalidaEste);
                    TextView tv = (TextView)v.findViewById(R.id.tv_pendiente);
                    tv.setText(Formato.double2Screen(rpf.getPorPagar()));
                }
            }
            catch (Exception e)
            {
                Log.e("MY_LOG", "FAIL");
                Log.e("MY_LOG", String.valueOf(invalidaEste));
            }

        }

invalidaEste 是我要修改的视图。 当 v 为 null 时,我会记录索引以检查它是否正常。总是小于或等于 listView.getCount()

为什么会这样?

更多数据:代码位于 AnimationListener 侦听器的 onAnimationStart(Animation animation) 内。

【问题讨论】:

标签: android view android-listview


【解决方案1】:

由于视图回收,listView.getChildAt() 将只返回它正在显示的位置的视图,可能还会返回一个。也许如果您分享更多代码,我们可以帮助您找出解决问题的最佳方法。

【讨论】:

  • 空视图是可见视图。
  • mmm...我想我明白你的意思了...当索引为0的视图不可见时会触发问题...我误解了getChildAt()方法...
  • 这真的坏了吗?我看到你已经是这个检查:if(invalidaEste &gt;= lv_data.getFirstVisiblePosition() &amp;&amp; invalidaEste &lt;= lv_data.getLastVisiblePosition()),当你滚动到视图中时,适配器应该更新任何其他视图。
  • 谢谢....我确实使用 (invalidaEste-lv_data.getFirstVisiblePosition()) 作为索引,现在可以正常工作...!!
  • 你们能告诉我什么是invalidaEste吗?我也面临同样的问题
【解决方案2】:

Dmon 和 Azertiti 都是正确的……一旦滚动您的列表,您就会发现自己有麻烦了。如果视图不可见,则它不存在(即已被 Android 回收)。滚动后,您将重新构建视图。

这样做应该可以:

View view;

int nFirstPos = lv_data.getFirstVisiblePosition();
int nWantedPos = invalidaEste - nFirstPos;

if ((nWantedPos >= 0) && (nWantedPos <= lv_data.getChildCount())
{
 view = lv_data.getChildAt(nWantedPos);
 if (view == null)
  return;
 // else we have the view we want
}

【讨论】:

    【解决方案3】:

    如果该孩子在屏幕上不可见,则意味着它没有视图。我相信这是你不工作的情况。

    一个好的做法是更改列表适配器后面的数据并在适配器上调用 notifyDataSetChanged()。这将通知列表适配器已更改并再次绘制视图。

    如果您真的想手动更新视图,我想唯一的解决方案是在某处保留新值并等到视图变得可见。此时,您有一个有效的参考并且可以进行更新。

    【讨论】:

    • 感谢您的回答....正如您在代码中看到的,仅当索引属于可见项时,我才使用视图 (v)。我没有使用 notifyDataSetChanged() 因为它取消了 listView 中的动画。
    • 我看到你在 invalidaEste != -1 时得到了孩子。这并不意味着它是一个具有可见视图的索引,而是一个可能是一个好的索引。在您想要粘贴但不可见的代码之上是否有任何代码?
    • invalidaEste != -1 只告诉我这是一个有效的索引。我使用 if(invalidaEste >= lv_data.getFirstVisiblePosition() && invalidaEste
    【解决方案4】:

    当我需要进入 Listview 的有效位置时,我会使用一行代码对其进行测试。这是用作示例的变量。其中 lv_data 是 ListView 而 tv 是您的 TextView。

    if ( lv_data.getChildAt(lv_data.getPositionForView(tv)) != null) {
        int position = lv_data.getPositionForView(tv);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多