作者Y78 (Y78)
看板AndroidDev
標題[分享] 簡單易學 自訂ListView
時間Thu Dec 27 11:32:57 2012
最近在研究如何自訂一個ListView
版上givemepass大大的這篇文章已經講得不錯了
#1DbiQ5jJ (AndroidDev) [ptt.cc] [分享] BaseAdapter 自定ListView
建議大家可以先看過這篇
至於這篇的話就分享一下最近使用的心得跟方法
如果哪裡有講錯的話還請大家幫忙指正一下
先來看看看完這篇文章之後可以做出的效果
----
【HBO電影台】
狙擊陌生人
20:00
禁運品
22:00
殺客同萌
23:55
【東森洋片台】
哈利波特2
17:35
飛機上有蛇
20:00
衝出封鎖線
23:15
----
程式截圖:
http://ppt.cc/YaGO
首先,有一個重點知道以後自訂ListView就不再那麼神秘
那就是List的每一列可以看成都是一個view
所以第一步就是就是決定每一列到底要長什麼樣子
以我想要達成的效果來說
我的item需要有兩個TextView
一個放電影名稱或是電影台的名稱
另外一個則放時間
所以建立一個 list_item.xml 來達成這個layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="
http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/title" />
</RelativeLayout>
上面的id叫做title 下面的則叫做time
接著,你要決定你的每一個item需要哪些資料
為了以後的方便,我們要自己建一個class來放這些資料
以這篇為例子
我要傳入的資料有:電影台名稱 電影標題 電影時間
其實我的case比較特殊啦
因為可以很明顯看到每個list item長的並不是很相同
所以我加了一個type的參數
type 0 = 這個item是電影 顏色是白色
type 1 = 這個item是電影台
type 2 = 這個item是電影 顏色是黃色
所以我的參數有 type , title(電影or電影台名稱),time(電影時間)
class叫做Movie.class 內容很簡單的長這樣
public class Movie {
private int type;
private String name;
private String time;
public Movie(int type,String name,String time) {
this.type = type;
this.name = name;
this.time = time;
}
public int getType(){
return type;
}
public void setType(int type){
this.type = type;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getTime(){
return time;
}
public void setTime(String time){
this.time = time;
}
}
再來先回到需要ListView的地方
假設ListView的id叫做ListView01好了
我們先宣告三個東西
private ListView listV;
List<Movie> movie_list = new ArrayList<Movie>();
private MyAdapter adapter;
MyAdapter是什麼呢? 是我們等一下會講到的東西
接著
listV=(ListView)findViewById(R.id.ListView01);
movie_list就是你要傳入的東西
以本篇為例 就是
movie_list.add(new Movie(1,"HBO電影台",""));
movie_list.add(new Movie(0,"綠光戰警","7:00"));
movie_list.add(new Movie(2,"鋼鐵人","9:00"));
movie_list.add(new Movie(0,"蝙蝠俠:開戰時刻","11:00"));
movie_list.add(new Movie(1,"衛視電影台",""));
movie_list.add(new Movie(0,"海角七號","7:00"));
movie_list.add(new Movie(2,"陣頭","9:00"));
movie_list.add(new Movie(0,"星空","11:00"));
這樣movie_list就是你想要的資料了
而且因為是把自訂的class放進去
所以很適合重複利用
例如說你今天想呈現的是一組聯絡人資料(姓名 手機 地址...)
你就依照上面的步驟自訂一個class Userinfo
然後改成 user_list.add(new Userinfo(...));就好了
接著設定一下adapter
adapter = new MyAdapter(Main.this,movie_list);
^^^^你的activity的class
listV.setAdapter(adapter);
這樣就只剩下最後一個部份了
那就是MyAdapter這個class
最一開始長這樣
public class MyAdapter extends BaseAdapter{
}
接下來我們一步一步加進幾個必要的東西進來
首先我們需要
private LayoutInflater myInflater;
private List<Movie> movies;
然後我們在MyAdapter建立的時候順便傳入兩個東西
public MyAdapter(Context context,List<Movie> movie){
myInflater = LayoutInflater.from(context);
this.movies = movie;
}
movies就是你傳入的整個list
也就是你想要建立的東西
接著我們再加入幾個method 程式碼應該不難理解我就不多做說明
@Override
public int getCount() {
return movies.size();
}
@Override
public Object getItem(int arg0) {
return movies.get(arg0);
}
@Override
public long getItemId(int position) {
return movies.indexOf(getItem(position));
}
最後重點就是getView了
在這之前我們先宣告一下inner class
private class ViewHolder {
TextView txtTitle;
TextView txtTime;
public ViewHolder(TextView txtTitle, TextView txtTime){
this.txtTitle = txtTitle;
this.txtTime = txtTime;
}
}
方便我們之後設定每一列的資料
getView一開始長這樣
@Override
public View getView(int position, View convertView, ViewGroup parent) {
}
接著我們一步一步添加東西
ViewHolder holder = null;
if(convertView==null){
convertView = myInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder(
(TextView) convertView.findViewById(R.id.title),
(TextView) convertView.findViewById(R.id.time)
);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
有關tag的功用 請參考這篇
http://www.cnblogs.com/qingblog/archive/2012/07/03/2575145.html
接著先取得現在要做的的資料
Movie movie = (Movie)getItem(position);
然後開始設定
//標題的顏色
int color_title[] = {Color.WHITE,Color.WHITE,Color.YELLOW};
//時間的顏色
int color_time[] = {Color.WHITE,Color.WHITE,Color.YELLOW};
//背景的顏色
int color_back[] = {Color.BLACK,Color.BLUE,Color.BLACK};
//時間是否顯示
int time_vis[] = {View.VISIBLE,View.GONE,View.VISIBLE};
int type_num = movie.getType();
holder.txtTitle.setText(movie.getName());
holder.txtTitle.setTextColor(color_title[type_num]);
holder.txtTitle.setBackgroundColor(color_back[type_num]);
holder.txtTime.setText(movie.getTime());
holder.txtTime.setTextColor(color_time[type_num]);
holder.txtTime.setVisibility(time_vis[type_num]);
因為我的list並不是每一個item都長一樣所以才需要這樣設定
像是如果type是1 代表只需要顯示一個電影台名稱而已
就要把背景設成藍色 時間也不需要顯示所以設成View.GONE
如果你的每個item都長一樣就不需要那麼大費周章了
最後記得 return convertView;
完整程式碼在這裡: MyAdapter.java
http://pastebin.com/GxBfpdCB
如此一來就大功告成了 順利顯示出我們想要的結果
使用自訂class的好處就是當我們以後有不同需求的時候
就像一個範本可以自己隨意修改
這篇也提供了一個固定的建立自訂ListView的流程
1.建一個list_item.xml 在res/layout下 看你每一列想要長怎樣
2.寫一個[ ].java 裡面說明你的資料結構為何
(例:Movie.java
http://pastebin.com/DWDx3EqW )
3.寫一個MyAdapter.java
其實程式的結構無須修改
只要一些細節需要調整而已
這篇的作法基本上是參考
http://tinyurl.com/clen3tn
步驟清晰易懂也有附上完整的code
ListView有個很方便的功能叫做setTextFilterEnabled
可以很方便的做到搜尋的功能
但是自從我們自訂ListView的內容以後
顯然這個方法不能直接套用 所以要自己override一些東西
下一篇將延續這一篇的作法,說明如何針對自訂的ListView做搜尋
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.198.74
推 ian90911:推 12/27 13:23
推 givemepass:講的很詳細 感謝你的分享 12/27 13:39
推 givemepass:其實我做過一個專案也是節目表 其中有一個問題 12/27 13:43
→ givemepass:就是當片名太長的時候 會變跑馬燈模式 12/27 13:43
→ givemepass:也是在MyAdapter裡面做調整就好 12/27 13:44
推 pkmilk:推~ 12/29 13:28