在listview中重绘单行
是否有可能在ListView
重绘单个行? 我有一个ListView
的LinearLayout
的行。 我倾听一个偏好改变,有时我需要改变一个单一行的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);
然后你用视图做任何你想做的事情。