想要讓 ListView 顯示比較複雜的樣子,可以利用自訂 Adapter 的方式來達到目的。
1、首先先建立一個 list_view_item.xml,把每個項目要顯示的樣子先設定好。
list_view_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <RelativeLayout android:gravity="left" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_date" android:layout_width="250px" android:layout_height="wrap_content" android:layout_weight="6" android:textSize="21dip" android:textStyle="bold" android:textColor="#FF00FF00" ></TextView> </RelativeLayout> <RelativeLayout android:gravity="right" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_company" android:layout_width="150px" android:layout_height="wrap_content" android:layout_weight="4" android:textSize="18dip" android:textStyle="bold" android:textColor="#FF0000" ></TextView> </RelativeLayout> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <RelativeLayout android:gravity="left" android:layout_weight="2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_money" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dip" android:textColor="#AAAAAA" ></TextView> </RelativeLayout> <RelativeLayout android:gravity="right" android:layout_weight="2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_miles" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dip" android:textColor="#AAAAAA" ></TextView> </RelativeLayout> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <RelativeLayout android:gravity="left" android:layout_weight="2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_price_per_litre" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dip" android:textColor="#AAAAAA" ></TextView> </RelativeLayout> <RelativeLayout android:gravity="center" android:layout_weight="2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_price_per_mile" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dip" android:textColor="#AAAAAA" ></TextView> </RelativeLayout> <RelativeLayout android:gravity="right" android:layout_weight="2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/ListItem_miles_per_litre" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dip" android:textColor="#AAAAAA" ></TextView> </RelativeLayout> </LinearLayout> </LinearLayout>
當然,也要設定一個包含 ListView 的 xml 檔給 Activity 使用。
list_iew.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>2、Adapter 本身要 extends BaseAdapter,內容最主要是設定 getView( ) 函式去決定 ListView 的項目該怎麼顯示,而資料的提供來源是一個 ArrayList<HashMap<String, String>> 型態的物件,也就是一個 ArrayList 的每個項目都是 HashMap,而每個 HashMap 都包含 String, String 兩個字串。
ListViewItem.java
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class OilListAdapter extends BaseAdapter {
private ArrayList<HashMap<String, String>> data;
private LayoutInflater layoutInflater;
public OilListAdapter (Context context, ArrayList<HashMap<String, String>> dt) {
this.data = dt;
this.layoutInflater = LayoutInflater.from(context); // 取得 LayoutInflater
}
public int getCount() {
return this.data.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return this.data.get(position);
}
public long getItemId(int arg0) {
return 0;
}
public View getView(int position, View view, ViewGroup parent) {
// TODO Auto-generated method stub
if(view == null) // 設定 ListView 的 item 要使用的 View
view = this.layoutInflater.inflate(R.layout.list_item, null);
// 讀取要顯示的 TextView
TextView date = (TextView) view.findViewById(R.id.OilListItem_date);
TextView company = (TextView) view.findViewById(R.id.ListItem_company);
TextView miles = (TextView) view.findViewById(R.id.ListItem_miles);
TextView money = (TextView) view.findViewById(R.id.ListItem_money);
TextView milesPerLitre = (TextView) view.findViewById(R.id.ListItem_miles_per_litre);
TextView pricePerLitre = (TextView) view.findViewById(R.id.ListItem_price_per_litre);
TextView pricePerMile = (TextView) view.findViewById(R.id.ListItem_price_per_mile);
// 填入項目的內容
date.setText(this.data.get(position).get("refuel_date"));
company.setText(this.data.get(position).get("refuel_company"));
miles.setText(this.data.get(position).get("refuel_miles")+"公里");
money.setText(this.data.get(position).get("refuel_price")+"元");
pricePerLitre.setText("油價:"+getPricePerLitre(position, arith)+"元/公升"); //油價
pricePerMile.setText(getPricePerMile(position, arith)+"元/公里"); // 單位油價
milesPerLitre.setText(getAvgOfMilesPerLitre(position, arith)+"公里/公升"); //本次油耗
return view;
}
}
3、 設定好 Adapter 之後,要在程式中設定 ListView 要以這個 Adapter 作為資料存取的來源。
ListActivity.java
public class RecordList extends ListActivity {
private ListView List;
private ListAdapter ListAdapter;
private ArrayList<HashMap<String, String>> ListArray; // ListView 的項目清單
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view);
this.List = this.getListView();
this.setListView();
}
//----------------------------------------------------------//
//------------------------ ListView ------------------------//
//----------------------------------------------------------//
private void setListView () {
// 設定 ListView 的 Adapter
this.ListArray = new ArrayList<HashMap<String, String>>();
this.ListAdapter = new ListAdapter(this, this.ListArray);
this.List.setAdapter(this.ListAdapter);
this.updateRecordList();
}
//------------------------------------------------------------------//
//------------------------ update functions ------------------------//
//------------------------------------------------------------------//
/**
* 更新列表內容
*/
private void updateRecordList () {
this.ListArray.clear();
SQLiteDatabase db = this.openOrCreateDatabase(db_name, Context.MODE_PRIVATE, null);
String sql = "SELECT * FROM table";
Cursor cs = db.rawQuery(sql, null);
HashMap<String, String> hm;
int numOfRows = cs.getCount();
cs.moveToFirst();
for(int i=0 ; i<numOfRows ; i++) {
hm = new HashMap<String, String>();
hm.put("refuel_id", cs.getString(0));
hm.put("refuel_company", cs.getString(2)); // 廠商名稱
hm.put("refuel_amount", cs.getString(3)); // 加油量
hm.put("refuel_miles", cs.getString(4)); // 里程
hm.put("refuel_price", cs.getString(5)); // 加油金額
hm.put("refuel_date", cs.getString(6)); // 加油日期
this.ListArray.add(hm);
cs.moveToNext();
}
db.close();
this.ListAdapter.notifyDataSetChanged();
}
}其中 updateRecordList() 這個函式是我設定來更新資料的,動作是從資料庫讀取資料後,填到 ArrayList<HashMap<String, String>> 裡,然後通知 Adapter 資料有更新。
沒有留言:
張貼留言