【问题标题】:Redraw a single row in a listview [duplicate]重绘列表视图中的单行[重复]
【发布时间】:2011-05-03 19:44:40
【问题描述】:

是否可以重绘ListView 中的单行?我有一个ListView,其中的行是LinearLayouts。我听取偏好更改,有时我只需要更改单行的LinearLayout 内的一个View。有没有办法让它重绘该行而不调用listview.notifyDatasetChanged()

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

【问题讨论】:

  • “有没有办法让它重绘该行而不调用 listview.notifydatasetchanged()?” -- 只需找到它作为ViewGroup 的子项(在本例中为ListView)并对其进行修改。 “我尝试在视图(在线性布局内)上调用 view.invalidate(),但它不会重绘行。” - 你确定你有正确的行吗?你甚至不需要打电话给invalidate(),AFAIK。
  • 我绝对有正确的行和正确的观点。我认为我的问题是我的偏好监听器正在被垃圾收集。我更改了它,所以我在我的活动的 onResume() 中调用 notifyDataSetChanged(),这解决了我试图解决的问题。

标签: android listview view android-arrayadapter redraw


【解决方案1】:

正如 Romain Guy explained a whileGoogle 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() 将重建整个列表并最终为每个显示的项目调用 getview() invalidateViews() 也会影响一堆。

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

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

在我们信任的代码中。

【讨论】:

  • 能否请您添加指向 Google I/O 会议本身的链接?我想检查整个会话。
  • +1 thx 为此,它很有趣 - 我假设它可以作为你将当前视图作为 convertView arg 传递,并且它将重置其视图元素 - 非常好
  • 这里不应该是 i
  • 我面临同样的问题。但是 list.getChildAt(position) 根据屏幕上显示的内容的索引返回子级。我提到了问题stackoverflow.com/q/29429704/2624806。任何建议!
  • @Ranjith 这是因为,当您上下滚动时,适配器的 getView() 方法会被调用,并且,如果您没有更改该行的数据,它将使用“旧“一个。
【解决方案2】:

view.invalidate() 对我不起作用。但这就像一个魅力:

假设您正在更新行中的位置“position”。 if 避免奇怪的重绘东西,比如当你在跳舞的时候文字跳舞 更新不在屏幕中的行。

            if (position >= listView.getFirstVisiblePosition()
                && position <= listView.getLastVisiblePosition()) {

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            listView.invalidateViews();
                        }
                    });
            }

【讨论】:

  • 它正在工作,伙计:) 但它似乎重新创建了所有行......有什么方法可以重新创建单行??
【解决方案3】:

Romain Guy 在“Google IO 2010 The world of ListView”上回答了这个问题 提出这个问题的确切时间的视频:http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s

所以根据 Romain Guy 的说法,这应该可行,而且我认为我们可以信任他。

你的视图没有重绘的原因有点神秘。 也许尝试禁用 listView 中所有可用的缓存选项

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

【讨论】:

  • 这不是他说的。他说getView方法仍然会被调用,但是在生成ui时引擎可以看到items数据没有改变,然后重复使用它们。
【解决方案4】:

在要更新的行上放置一些标签。 当您想重绘该特定视图或行时,请执行

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

然后

View v = lv.findViewWithTag(tagobject);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-24
    • 2011-06-22
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 2012-06-22
    相关资源
    最近更新 更多