Android中ListView的各種顯示效果

webphp 12年前發布 | 4K 次閱讀 網絡開發

在android應用開發中,ListView是使用頻率非常高的一個組件,基本上稍微復雜點的布局都會用到它,利用它可以讓你的界面美觀,有層次

。ListView可以用來作為數據顯示的容器,也可以作為界面的布局。學習ListView需要關注的內容大概有三點:顯示、數據適配器以及各種

事件的監聽器。內容有點多,這里先只講如何讓ListView達到你想要的顯示效果。
一、普通的ListView
普通的ListView是指每一個item只顯示一條文本數據,程序運行效果圖如下:


listview_general

代碼:

protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub     super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_listview_simple);

<span style="color:#008000;">//取得ListView實例</span>     ListView lvwSimple = (ListView)findViewById(R.id.lvw_simple);
<span style="color:#008000;">//要在ListView中顯示的數據集合</span>     String items[] = <span style="color:#0000ff;">new</span> String[] {<span style="color:#006080;">"item1"</span>, <span style="color:#006080;">"item2"</span>, <span style="color:#006080;">"item3"</span>, <span style="color:#006080;">"item4"</span>, <span style="color:#006080;">"item5"</span>};
<span style="color:#008000;">//new一個ArrayAdapter,android.R.layout.simple_list_item_1為ListView顯示的布局文件</span>     ArrayAdapter<String> adapter = <span style="color:#0000ff;">new</span> ArrayAdapter<String>(<span style="color:#0000ff;">this</span>, android.R.layout.simple_list_item_1, items);
<span style="color:#008000;">//位ListView設置Adapter</span>     lvwSimple.setAdapter(adapter);

}</pre></div>

二、自定義ListView

上面的那種方法只能顯示簡單的文字信息,顯然在很多場合下都不夠用,比如你想要在一個item中顯示圖片,顯示多行文字,這就需要你自定義ListView的布局了。

效果圖如下:

listview_custom

步驟:

1、分析你想要實現的布局效果,自定義布局文件lvw_custom.xml,該布局文件針對的是ListView的item,而不是整個ListView:

<?xml version="1.0" encoding="utf-8"?> <!-- 自定義布局文件 --> <LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="horizontal"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     >     <ImageView           android:id="@+id/lvw_custom_img"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_gravity="center_vertical"           android:layout_margin="5dip"    
          android:background="@drawable/custom"    
          />     <LinearLayout         xmlns:android="http://schemas.android.com/apk/res/android"         android:orientation="vertical"         android:layout_width="fill_parent"         android:layout_height="wrap_content">         <TextView 
            android:id="@+id/lvw_custom_name"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_marginLeft="5dip"             android:layout_marginRight="5dip"             android:layout_marginTop="5dip"             android:textSize="25dip"             android:text="item名稱"/>         <TextView 
            android:id="@+id/lvw_custom_description"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_margin="5dip"             android:textSize="10dip"             android:text="item描述..."/>     </LinearLayout> </LinearLayout>

2、取得用于ListView的數據集合,類型是ArrayList<Map<String, Object>>,每一個Map對應于ListView的一個item,多個map就構成了ListView的數據集合:

/**      * 取得用于ListView的數據      * @return      */     private ArrayList<HashMap<String, Object>> getItems() {
        ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>();
        for(int i = 0; i < 5; i++) {
            //***********************************************             //* 每一個map中的數據對應與ListView中的一個item *             //* 在我自定義的布局文件中,一個item包括:      *             //* 1、圖片(lvw_custom_img)                   *             //* 2、名稱(lvw_custom_name)                  *             //* 3、描述(lvw_custom_description)           *             //* 所以map中也至少需要包括這三項數據           *             //***********************************************             HashMap<String, Object> map = new HashMap<String, Object>();
            //圖片,key值可以隨便取,映射關系會在實例化Adapter時定義,但我喜歡將key與布局文件中定義的id取同樣的值             //value值為圖片的資源id             map.put("lvw_custom_img", R.drawable.custom);
            //名稱             map.put("lvw_custom_name", "item名稱");
            //描述             map.put("lvw_custom_description", "item描述");

        items.add(map);
    }
    <span style="color:#0000ff;">return</span> items;
}</pre></div>

3、為ListView設置SimpleAdapter:

//取得ListView實例         ListView lvwCustom = (ListView)findViewById(R.id.lvw_custom);
        //要在ListView中顯示的數據集合         ArrayList<HashMap<String, Object>> items = getItems();
        //************************************************************************         //* new一個SimpleAdapter                                                 *         //* items為數據集合                                                      *         //* R.layout.lvw_custom為自定義的ListView布局文件                        *         //* 第四個參數為map中德key集合                                           *         //* 第五個參數為自定義布局文件中空間的資源id集合,與第四個參數要一一對應 *         //************************************************************************         SimpleAdapter adapter = new SimpleAdapter(this, items, R.layout.lvw_custom, 
                new String[] {"lvw_custom_img","lvw_custom_name","lvw_custom_description"}, 
                new int[] {R.id.lvw_custom_img, R.id.lvw_custom_name, R.id.lvw_custom_description});
        //位ListView設置Adapter         lvwCustom.setAdapter(adapter);

三、顯示非資源id類型圖片的ListView

通過上面的例子可以看到Map中圖片項的value是資源id,這是針對項目中已存在的圖片文件,為什么要用資源id而不是其他(比如Bitmap類型)呢,這是因為adapter的bindView()方法是負責解析圖片并將其顯示到ImageView中,但它只針對資源id類型做了判斷。然而有一種情況,比如你的圖片是從網絡讀取的Bitmap類型,你就需要對代碼進行改寫了。分析SimpleAdapter的源碼,發現getView()方法是負責夠造界面布局的的,而getView又是調用bindView來往控件里填充值的,所以我這里對bindView()方法進行改寫。新建一個類CustomImageAdapter,代碼完全copy自SimpleAdapter,找到bindView方法,對其進行改寫:

private void bindView(int position, View view) {
        final Map dataSet = mData.get(position);
        if (dataSet == null) {
            return;
        }

    <span style="color:#0000ff;">final</span> ViewBinder binder = mViewBinder;
    <span style="color:#0000ff;">final</span> View[] holder = mHolders.get(view);
    <span style="color:#0000ff;">final</span> String[] from = mFrom;
    <span style="color:#0000ff;">final</span> <span style="color:#0000ff;">int</span>[] to = mTo;
    <span style="color:#0000ff;">final</span> <span style="color:#0000ff;">int</span> count = to.length;

    <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = 0; i < count; i++) {
        <span style="color:#0000ff;">final</span> View v = holder[i];
        <span style="color:#0000ff;">if</span> (v != null) {
            <span style="color:#0000ff;">final</span> Object data = dataSet.get(from[i]);
            String text = data == null ? <span style="color:#006080;">""</span> : data.toString();
            <span style="color:#0000ff;">if</span> (text == null) {
                text = <span style="color:#006080;">""</span>;
            }

            <span style="color:#0000ff;">boolean</span> bound = false;
            <span style="color:#0000ff;">if</span> (binder != null) {
                bound = binder.setViewValue(v, data, text);
            }

            <span style="color:#0000ff;">if</span> (!bound) {
                <span style="color:#0000ff;">if</span> (v <span style="color:#0000ff;">instanceof</span> Checkable) {
                    <span style="color:#0000ff;">if</span> (data <span style="color:#0000ff;">instanceof</span> Boolean) {
                        ((Checkable) v).setChecked((Boolean) data);
                    } <span style="color:#0000ff;">else</span> {
                        <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> IllegalStateException(v.getClass().getName() +
                                <span style="color:#006080;">" should be bound to a Boolean, not a "</span> + data.getClass());
                    }
                } <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (v <span style="color:#0000ff;">instanceof</span> TextView) {
                    <span style="color:#008000;">// Note: keep the instanceof TextView check at the bottom of these</span>                         <span style="color:#008000;">// ifs since a lot of views are TextViews (e.g. CheckBoxes).</span>                         setViewText((TextView) v, text);
                } <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (v <span style="color:#0000ff;">instanceof</span> ImageView) {
                    <span style="color:#0000ff;">if</span> (data <span style="color:#0000ff;">instanceof</span> Integer) {
                        setViewImage((ImageView) v, (Integer) data);                            
                    } 
                    <span style="color:#008000;">//這里增加對Bitmap類型的判斷</span>                             <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span>(data <span style="color:#0000ff;">instanceof</span> Bitmap) {
                        ((ImageView)v).setImageBitmap((Bitmap)data);
                    }
                    <span style="color:#0000ff;">else</span> {
                        setViewImage((ImageView) v, text);
                    }
                } <span style="color:#0000ff;">else</span> {
                    <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> IllegalStateException(v.getClass().getName() + <span style="color:#006080;">" is not a "</span> +
                            <span style="color:#006080;">" view that can be bounds by this SimpleAdapter"</span>);
                }
            }
        }
    }
}</pre></div>

然后像自定義ListView的步驟一樣使用就行了,只是把SimpleAdapter替換為CustomImageAdapter,Map中圖片項的value變為Bitmap類型了。

四、Item使用不同布局的ListView

通過前面的例子可以看到,ListView的所有item使用的都是相同的布局,如果想使用不同的布局呢?

這個例子是我從以前做的音樂播放器代碼里找的,效果圖:

listview_different

MP3的封面圖片突然不顯示了,不知道咋回事。

步驟:

1、在Map中存放的鍵值對中多增加一項布局類型:

/**      * 根據playlistId獲得歌曲列表,用于ListView顯示      *       * @param playlistId      *            0表示所有歌曲      * @return      */     private List<Map<String, Object>> getSongList(int playlistId) {

    <span style="color:#008000;">// 取得符合條件的所有歌曲</span>         List<Song> songs = getSongs(playlistId);
    <span style="color:#008000;">// 構造SongList的數據</span>         List<Map<String, Object>> list = <span style="color:#0000ff;">new</span> ArrayList<Map<String, Object>>();

    Map<String, Object> map1 = <span style="color:#0000ff;">new</span> HashMap<String, Object>();
    <span style="color:#008000;">//這里的Type是用于在getView方法中判斷并構造布局的</span>         map1.put(<span style="color:#006080;">"type"</span>, TYPE_BTN);
    map1.put(<span style="color:#006080;">"id"</span>, ID_RANDOM_PLAY);
    map1.put(<span style="color:#006080;">"mainlist_btn_name"</span>, <span style="color:#006080;">"隨機播放"</span>);
    map1.put(<span style="color:#006080;">"mainlist_btn_img"</span>, R.drawable.list_random_icon);

    list.add(map1);

    <span style="color:#0000ff;">if</span> (songs != null) {
        <span style="color:#0000ff;">int</span> size = songs.size();
        <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = 0; i < size; i++) {
            Song song = songs.get(i);
            Map<String, Object> map = <span style="color:#0000ff;">new</span> HashMap<String, Object>();
            <span style="color:#008000;">//這里的Type是用于在getView方法中判斷并構造布局的</span>                 map.put(<span style="color:#006080;">"type"</span>, TYPE_SONG_LIST);
            map.put(<span style="color:#006080;">"id"</span>, song.getId());
            Bitmap bm = MusicHelper.getArtwork(<span style="color:#0000ff;">this</span>, song.getId(), song
                    .getAlbumId(), true);
            map.put(<span style="color:#006080;">"songlist_cover_img"</span>, bm);
            map.put(<span style="color:#006080;">"songlist_song_name"</span>, song.getTitle());
            map.put(<span style="color:#006080;">"songlist_song_album"</span>, song.getAlbum());
            map.put(<span style="color:#006080;">"songlist_song_artist"</span>, song.getArtist());
            list.add(map);
        }
    }
    <span style="color:#0000ff;">return</span> list;
}</pre></div>

2、為不同的item布局分別定義不同的布局文件。

list_songs.xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     >     <ImageView           android:id="@+id/songlist_cover_img"           android:layout_width="48dip"           android:layout_height="48dip"           android:layout_alignParentLeft="true"           android:layout_centerVertical="true"           android:layout_marginLeft="6dip"        
          />      <LinearLayout          android:orientation="vertical"          android:layout_width="fill_parent"          android:layout_height="wrap_content"          android:layout_toRightOf="@id/songlist_cover_img"          android:layout_alignParentRight="true"          android:layout_centerVertical="true">          <TextView              android:id="@+id/songlist_song_name"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_marginTop="6dip"              android:layout_marginLeft="6dip"              android:layout_marginBottom="3dip"              android:textSize="24dip"              android:textColor="@drawable/black">          </TextView>          <RelativeLayout              android:layout_width="fill_parent"              android:layout_height="wrap_content"              android:layout_marginBottom="6dip">              <TextView                  android:id="@+id/songlist_song_album"                  android:layout_width="wrap_content"                  android:layout_height="wrap_content"                  android:layout_marginTop="3dip"                  android:layout_marginLeft="6dip"                  android:textSize="10dip"                  android:textColor="@drawable/black">              </TextView>              <TextView                  android:id="@+id/songlist_song_artist"                  android:layout_width="wrap_content"                  android:layout_height="wrap_content"                  android:layout_marginTop="3dip"        
                 android:layout_marginRight="6dip"                  android:layout_alignParentRight="true"                  android:textSize="10dip"                  android:textColor="@drawable/black">              </TextView>          </RelativeLayout>      </LinearLayout> </RelativeLayout> 

list_main_btn.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="horizontal"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     >     <TextView              android:id="@+id/mainlist_btn_name"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_marginLeft="6dip"              android:layout_marginTop="10dip"              android:layout_marginBottom="10dip"             android:layout_gravity="center_vertical"              android:textSize="28dip"              android:textColor="@drawable/black"/>     <ImageView           android:id="@+id/mainlist_btn_img"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_gravity="center_vertical"           android:layout_marginLeft="6dip"        
          /> </LinearLayout>

3、自定義Adapter類SongListAdapter,繼承自BaseAdapter,重寫getView方法,在該方法中使用LayoutInflator,根據map中定義的布局類型,構造對應的布局:

<pre>@Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); //產生一個View View view = null;
//根據type不同的數據類型構造不同的View,0代表歌曲,1代表按鈕菜單 //這個list是ListView的數據項集合,是通過構造方法傳遞進來的 int type = (Integer)list.get(position).get("type"); if(0 == type) { view = inflater.inflate(R.layout.list_songs, null); //獲取songlist_cover_img ImageView songlist_cover_img = (ImageView)view.findViewById(R.id.songlist_cover_img); songlist_cover_img.setImageBitmap((Bitmap)list.get(position).get("songlist_cover_img")); //獲取songlist_song_name TextView songlist_song_name = (TextView)view.findViewById(R.id.songlist_song_name); String song_name = list.get(position).get("songlist_song_name").toString(); songlist_song_name.setText(song_name); //獲取songlist_song_album屬性 TextView songlist_song_album = (TextView)view.findViewById(R.id.songlist_song_album); String song_album = list.get(position).get("songlist_song_album").toString(); songlist_song_album.setText(song_album); //獲取songlist_song_artist屬性 TextView songlist_song_artist = (TextView)view.findViewById(R.id.songlist_song_artist); String song_artist = list.get(position).get("songlist_song_artist").toString(); songlist_song_artist.setText(song_artist); } else if(1 == type) { view = inflater.inflate(R.layout.list_main_btn, null); //獲取按鈕菜單的mainlist_btn_name屬性 TextView mainlist_btn_name = (TextView)view.findViewById(R.id.mainlist_btn_name); String btn_name = list.get(position).get("mainlist_btn_name").toString(); mainlist_btn_name.setText(btn_name); //獲取mainlist_btn_img ImageView mainlist_btn_img = (ImageView)view.findViewById(R.id.mainlist_btn_img); int resId = (Integer)list.get(position).get("mainlist_btn_img"); mainlist_btn_img.setImageResource(resId); } else {

    }

    <span style="color:#0000ff;">return</span> view;
}</pre></div>

3、為ListView設置adapter:

list = getSongList(playlistId);
SongListAdapter adapter = new SongListAdapter(list, this);
songList.setAdapter(adapter);
轉自:http://www.cnblogs.com/chenguanwei/archive/2011/12/09/2282421.html

 本文由用戶 webphp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!