2014-09-03 31 views

回答

0

您不应该尝试直接修改listview的子元素。相反,请修改适配器,以便根据某些条件显示徽章。

然后,修改适配器的基础数据(并在适配器上调用notifyDatasetChanged())和listview将自行重绘。

例如,将您的适配器视为由Song对象列表支持。在getView()中,如果((Song) get item(position)).isFavourited()返回true,则可以显示徽章。

要显示列表中第n首乐曲的徽章,您需要修改列表(songs.get(n).favourite())并致电adapter.notifyDatasetChanged()


使用更详细但不完全详尽的例子进行编辑。注意评论和TODO:

import android.view.View; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.ListAdapter; 

import java.util.ArrayList; 
import java.util.List; 

public class Test { 

    public static void test() { 
     List<Song> songsList = new ArrayList<Song>(); 
     songsList.add(new Song("Generic Song Title", false)); 
     songsList.add(new Song("Another Song Title", false)); 
     songsList.add(new Song("A Third Song Title", false)); 
     Songs songs = new Songs(songsList); 

     ListAdapter songsAdapter = new SongsAdapter(songs); 
     // TODO: ListView.setAdapter(songsAdapter) 

     /* 
     When you want to change the visibility on a badge of a given song, 
     do NOT modify the view by trying to access it from the ListView 
     using ListView.getChildAt(int). 

     Update the data, and give it to your adapter, as follows: 
     */ 
     List<Song> anotherSongsListWithFavourites = new ArrayList<Song>(); 
     songsList.add(new Song("Generic Song Title", false)); 
     songsList.add(new Song("Another Song Title", true)); 
     songsList.add(new Song("A Third Song Title", true)); 
     Songs modifiedSongs = new Songs(anotherSongsListWithFavourites); 
     ((SongsAdapter) songsAdapter).updateSongs(modifiedSongs); 
    } 

    public static void test2_updateExistingSongCollection() { 
     List<Song> songsList = new ArrayList<Song>(); 
     songsList.add(new Song("Generic Song Title", false)); 
     songsList.add(new Song("Another Song Title", false)); 
     songsList.add(new Song("A Third Song Title", false)); 
     Songs songs = new Songs(songsList); 

     ListAdapter songsAdapter = new SongsAdapter(songs); 
     // TODO: ListView.setAdapter(songsAdapter) 

     /* 
     Now we update the existing Songs object. The adapter's reference is 
     still pointing to it, so that data will change too, but the adapter 
     won't know. This means the data will not immediately update on screen, 
     unless the user scrolls up/down OR unless we tell the adapter to 
     call `notifyDatasetChanged()` which we'd have to expose another method 
     for because it's a `protected` method (not shown). 
     */ 
     songs.get(0).isFavourite = true; 
    } 

    private static class Song { 

     public final String songName; 
     // not final because we're grossly modifying this for the example in test2 
     public boolean isFavourite; 

     private Song(String songName, boolean isFavourite) { 
      this.songName = songName; 
      this.isFavourite = isFavourite; 
     } 

    } 

    private static class Songs { 

     private final List<Song> songs; 

     public Songs(List<Song> songs) { 
      this.songs = songs; 
     } 

     public Song get(int position) { 
      return songs.get(position); 
     } 

     public int size() { 
      return songs.size(); 
     } 

    } 

    private static class SongsAdapter extends BaseAdapter { 

     private Songs songs; 

     private SongsAdapter(Songs songs) { 
      this.songs = songs; 
     } 

     /* 
      Update the dataset, and then pass the new data to the adapter. 
      You could update an individual song, but I wouldn't recommmend it. 
      This adapter's responsibility is to take a Songs object map each one 
      to a View - it shouldn't have to deal with MODIFYING the dataset. 

      Note, the `notifyDataSetChanged()`. This tells the ListView to ask 
      the adapter for new views (with updated data). 
     */ 
     public void updateSongs(Songs songs) { 
      this.songs = songs; 
      notifyDataSetChanged(); 
     } 

     @Override 
     public int getCount() { 
      return songs.size(); 
     } 

     @Override 
     public Song getItem(int position) { 
      return songs.get(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      // we won't support stable IDs for this example 
      return 0; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      View view = convertView; 
      if (view == null) { 
       view = createNewView(); 
      } 
      update(view, songs.get(position)); 
      return view; 
     } 

     private View createNewView() { 
      // TODO: create a new instance of your view and return it 
      return null; 
     } 

     private void update(View view, Song song) { 
      // TODO: update the rest of the view 
      if (song.isFavourite) { 
       // TODO: show badge on view 
      } else { 
       // TODO: hide the badge on view 
      } 
     } 

    } 

} 
+0

谢谢我明白这个算法。但是我需要一个小例子代码。可以给你一个这个算法的例子吗? – 2014-09-03 21:43:13

+0

不是。我不知道你会在哪种情况下显示徽章。我看不出你是如何获取数据的('getItem()'),所以无法修改它。我会在明天尝试添加一个人为的例子。 – ataulm 2014-09-03 23:20:19

+0

我会等你的例子。 – 2014-09-04 07:55:02