0

我正在创建一种具有歌曲列表视图的音乐播放器(在当前播放歌曲附近有进度条)

重要的是我有一个带有可以从外部更改的视图的项目(在某些处理程序中)

 public View getView(int i, View convertView, ViewGroup viewGroup) {
   RelativeLayout result;

        if (convertView == null) {
            result = (RelativeLayout) inflater.inflate(R.layout.list_item, viewGroup, false);
        } else {
            result = (RelativeLayout) convertView;
        }

        ...
        ProgressBar progressBar = result.findViewById(R.id.progressBar)
        ...

        if (i == currentSong) {
           // saving to instance variable
           this.currentlyPlayingProgressBar = progressBar;
        } else {
           progressBar.setVisibility(View.GONE);
        }
        ...       
        return result;
}

(代码已更改以关注我的问题)

顺便说一句 currentSong 可以从外部更改,在这种情况下正在调用 adapter.notifyDataSetChanged() 。

似乎我使用 listView 不正确,但我不知道更好的方法。

主要问题是我需要链接到视图来更改它们。我能得到它们的唯一方法是在 getView 方法中,它以只有谷歌开发人员可以解释的方式重用这些视图=(


第一个问题

这一切都发生在 Fragment 中,它只是 viewPager 的一部分。当用户滚动此片段然后回滚时,将调用 getView 方法,其中包含一些奇怪的对象。我用这个无效值覆盖 currentPlayingProgressBar。这导致我的状态栏冻结。(它开始更新错误的视图)

而且我不知道它是哪种观点..


第二个问题

我正在重用列表项,这意味着当用户向下滚动列表视图时-有时他实际上会得到具有相同进度条的相同列表项。这个 progressBar 必须是不可见的,但它不是(我认为这完全是因为我从外部使用了 currentPlayingProgressBar)

提前致谢。

4

2 回答 2

0

您可以通过两种方式做到这一点:

1) notifyDataSetChanged,它只是重置整个 ListView 并将所有可见的列表项再次分配给视图。notifyDataSetChanged 非常昂贵,因为它会重新创建整个列表和视图层次结构,测量布局等,这很慢。对于单个列表项的频繁更新,例如进度条的变化,这是矫枉过正的。

2) 查找特定列表视图项目的视图,并仅更新该项目。我们将专注于这种方法。

首先,您需要以某种方式确定哪个列表视图包含哪个列表项。常见的方法是在 Adapter.getView 中使用View.setTag其中setTag 参数是您选择的对象,可能与您为Adapter.getItem返回的项目相同。所以后来你知道哪个 ListView 子视图分配了哪个项目。

假设您要更新 ListView 中显示的特定项目,您必须遍历 ListView 子视图以查找显示您的项目的视图:

Object myItem = ...;
for(int i = list.getChildCount(); --i>=0; ){
     View v = list.getChildAt(i);
     Object tag = v.getTag();
     if(tag==myItem) {
        // found, rebind this item
        bindItemToView(myItem, v);
        break;
     }
  }

您必须期望 ListView 当前可能不会显示您的列表项(已滚动)。

从上面的代码中,您可以看到它调用了 bindItemToView,这是您将项目绑定到列表视图的函数。您可能会调用相同的函数来在 Adapter.getView 中设置项目视图。

您还可以进一步优化它,假设您只想更新 ProgressBar,然后不要调用 bindItemToView,而是只更新列表项视图中的 ProgressBar(findViewById,设置值)。

提示:您可以使用ViewHolder 方法使其更加优化。然后 setTag 将不包含您的项目对象,而是您的 ViewHolder 对象。

于 2013-04-09T06:58:28.723 回答
0

@Pointer null 也提供了非常有用的方法,但是在您的情况下,我认为您正在更新不可见的列表,在这种情况下,您必须像列表索引一样从适配器设置标签,并相应地检查列表项是否存在于最后一个可见项目或第一个可见项目之间,然后更新它,否则不更新..

于 2013-08-13T14:36:38.423 回答