在listview中重绘单行

是否有可能在ListView重绘单个行? 我有一个ListViewLinearLayout的行。 我倾听一个偏好改变,有时我需要改变一个单一行的LinearLayout中的一个View 。 有没有办法让它重绘该行,而无需调用listview.notifyDatasetChanged()

我已经尝试调用view.invalidate()在视图( LinearLayout ),但它不重绘该行。

正如罗曼·盖伊(Romain Guy)在Google I / O会话期间解释的那样 ,在列表视图中更新一个视图的最有效方法如下(这个更新整个View数据):

 ListView list = getListView(); int start = list.getFirstVisiblePosition(); for(int i=start, j=list.getLastVisiblePosition();i<=j;i++) if(target==list.getItemAtPosition(i)){ View view = list.getChildAt(i-start); list.getAdapter().getView(i, view, list); break; } 

假设target是适配器的一个项目。

这段代码检索ListView ,然后浏览当前显示的视图,将你正在寻找的target项目与每个显示的视图项目进行比较,如果你的目标是在这些视图项目之间,那么获取包含视图并在该视图上执行适配器getView()刷新显示。

作为一个方面的说明invalidate()不像一些人所期望的那样工作,并且不会像getView()那样刷新视图, notifyDataSetChanged()将重build整个列表并最终为每个显示的项目调用getview() ,而invalidateViews()也会影响一堆。

最后一件事情是,如果他只需要改变一个行视图的子项而不是像getView那样的整行,也可以获得额外的性能。 在这种情况下,下面的代码可以替代list.getAdapter().getView(i, view, list); (例如更改TextView文本):

 ((TextView)view.findViewById(R.id.myid)).setText("some new text"); 

在我们信任的代码中。

view.invalidate()不适合我。 但是,这就像一个魅力:

设置你正在更新行中的位置“ position ”。 if避免奇怪的重绘东西,就像在更新不在屏幕中的行时跳舞的文本一样。

  if (position >= listView.getFirstVisiblePosition() && position <= listView.getLastVisiblePosition()) { runOnUiThread(new Runnable() { @Override public void run() { listView.invalidateViews(); } }); } 

Romain Guy回答了这个问题,在“Google IO 2010 ListView”video的这个问题的确切时间被问到: http : //www.youtube.com/watch?feature= player_detailpage& v= wDBM6wVEO70#t=3149s

所以根据罗曼·盖伊的说法,这应该起作用,我想我们可以相信他。

你的观点不被重新绘制的原因有点神秘。 也许尝试禁用listView中可用的所有caching选项

 setAnimationCacheEnabled(false); setScrollingCacheEnabled(false); setChildrenDrawingCacheEnabled(false); setChildrenDrawnWithCacheEnabled(false); 

在你想要更新的行上放一些标签。 当你想重画那个特定的视图或行时,

 ListView lv = (ListView)findViewById(....) 

接着

 View v = lv.findViewWithTag(tagobject); 

然后你用视图做任何你想做的事情。