是否可以在ListView
中重绘一行?我有ListView
行LinearLayout
s。我听取偏好更改,有时我需要在单行的View
内更改一个LinearLayout
。有没有办法让它重新绘制该行而不调用listview.notifyDatasetChanged()
?
我尝试在视图上调用view.invalidate()(在LinearLayout
内),但它没有重绘行。
答案 0 :(得分:105)
作为Romain Guy explained a while回到Google I/O session期间,仅在列表视图中更新一个视图的最有效方法如下(此更新整个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()
将重建整个列表并最终调用{{ 1}}对于每个显示的项目,getview()
也会影响一堆。
最后一件事,如果他只需要更改行视图的子项而不是像invalidateViews()
这样的整行,那么也可以获得额外的性能。在这种情况下,以下代码可以替换getView
(例如更改list.getAdapter().getView(i, view, list);
文本):
TextView
在我们信任的代码中。
答案 1 :(得分:6)
view.invalidate()
对我不起作用。但这就像一个魅力:
假设您正在更新行中的“position
”位置。
if
避免了怪异的重绘内容,就像文字跳舞一样
更新不在屏幕中的行。
if (position >= listView.getFirstVisiblePosition()
&& position <= listView.getLastVisiblePosition()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
listView.invalidateViews();
}
});
}
答案 2 :(得分:3)
Romain Guy在“Google IO 2010 ListView的世界”中回答了这个问题 在提出此问题的确切时间的视频:http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s
根据Romain Guy的说法,这应该有效,我认为我们可以信任他。
您的视图未重绘的原因有点神秘。 也许尝试禁用listView中可用的所有缓存选项
setAnimationCacheEnabled(false);
setScrollingCacheEnabled(false);
setChildrenDrawingCacheEnabled(false);
setChildrenDrawnWithCacheEnabled(false);
答案 3 :(得分:0)
在要更新的行上添加一些标记。 如果要重绘特定视图或行,请执行
ListView lv = (ListView)findViewById(....)
然后
View v = lv.findViewWithTag(tagobject);
然后你用视图做任何你想做的事。