Android ListView在滚动后才显示条目

3
我正在开发一个Android应用程序,其中一部分是显示包含复选框以允许选择的歌曲列表。我正在使用自定义列表适配器来实现此功能。代码似乎可以加载并使用复选框,但唯一的问题是只有在滚动列表之后其他项目才会呈现文本。我知道这可能是列表视图没有刷新或类似问题,但我无法找出如何修复它。
以下是我的适配器代码:
private class PlaylistDetailsAdapter extends ArrayAdapter<Song> {

    boolean[] checkBoxState;
    ViewHolder viewHolder;

    public PlaylistDetailsAdapter(Context context, int textViewResourceId, ArrayList<Song> songs) {
        super(context, textViewResourceId, songs);
        checkBoxState = new boolean[songs.size()];
    }

    private class ViewHolder {
        TextView songName;
        CheckBox checkBox;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.activity_playlist_details_row, null);
            viewHolder = new ViewHolder();

            viewHolder.songName = (TextView)convertView.findViewById(R.id.playlist_details_song_name);
            viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.playlist_details_checkbox);
            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (ViewHolder)convertView.getTag();
            Song song = playlistSongs.get(position);
            viewHolder.songName.setText(song.getTitle() + " - " + song.getArtist());
            viewHolder.checkBox.setChecked(checkBoxState[position]);
            viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (((CheckBox)v).isChecked()) {
                        checkBoxState[position] = true;
                    }
                    else {
                        checkBoxState[position] = false;
                    }
                }
            });

        }

        return convertView;
    }

}

以下是设置列表视图的代码:

playlistSongs = db.getPlaylistTracks(getIntent().getLongExtra("id", 0));

    TextView playlistName = (TextView)findViewById(R.id.playlist_details_name);
    playlistName.setText(getIntent().getStringExtra("name"));

    final PlaylistDetailsAdapter adapter = new PlaylistDetailsAdapter(this, R.layout.activity_playlist_details_row, playlistSongs);

    ListView playlistSongList = (ListView)findViewById(R.id.listview_playlist_details);

    playlistSongList.setAdapter(adapter);

任何帮助都将不胜感激。
谢谢。

在各个方面,getView方法都是导致这个问题的原因,我目前不确定具体原因,但我曾经遇到过同样的问题,这是由于Android元素的可重用设计所引起的。 - Nickolaus
3个回答

5
问题在于当convertView==null时,您没有将数据放入视图中,只是设置了如何查找它们。
您需要做的是从“else”部分中删除实际更改视图的代码,并将其放置在整个if-else区域之后。
例如:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
     ...
    }
    else 
        viewHolder = (ViewHolder)convertView.getTag();
    // now we have the views ready to be changed , so change them :
    Song song = playlistSongs.get(position);
    ...
    return convertView;
}

1
如果您愿意,您也可以观看Google的“listView世界”的讲座。我认为这可以帮助很多新手了解listView。 - android developer

0

调用:

adapter.notifyDataSetChanged() 

当您的列表包含新数据时


正确的时机没有调用 notifyDataSetChanged() - Nickolaus
感谢您的建议,我尝试在设置适配器之后添加了那行代码,但它没有解决问题。 - peppermcknight
在你的“notifyDataSetChanged”之后尝试使用invalidate()来使你的视图无效。 - Tom Mekken

0

你好,朋友。你可以使用水平或垂直滚动视图来解决这个问题,因为你知道ListView每次都会被回收。

我以前也遇到过这个问题,后来我使用滚动视图代替了ListView。

然后,创建一个布尔类型的ArrayList,大小与你的列表项相同,并首先将所有值设置为false。之后,你就可以使用你的代码了。

           @Override
            public void onClick(View v) {
                if (((CheckBox)v).isChecked()) {
                    checkBoxState[position] = true;
                }
                else {
                    checkBoxState[position] = false;
                }
            }
        });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接