幾乎元件在使用自定義的方式呈現時最常出現的一個子類別
因為自定義的view是自由設定的,所以不能像ArrayAdapter只是單純
只帶入資料而已,必須對view內的元件也做設定及加入事件等
也就是說主要的Activity只是建構此子類別,帶入相關需要的參數
其他的自定義view元件想要怎麼加、想要怎麼設定、做什麼事
都是在BaseAdapter內做設定就可以了,這樣說應該聽了還是霧煞煞
我們用實際的程式碼來邊做邊說明好了。
這裡我們用自定義的ListView來做說明:
ListView listView01 = (ListView)findViewById(R.id.listView1);
CharSequence[] list = MemorandumDate;
CharSequence[] list2 = MemorandumNote;
CharSequence[] list3 = MemorandumPW;
BaseAdapter adapter = new MyAdapter(this, list, mID, list2, list3, mreminder);
listView01.setAdapter(adapter);
說明:
在主要的Activity中,找到ListView元件,然後我們建構一個適配器adapter
CharSequence[]是字元陣列,用來儲存文字用的,我同時在其他地方有宣告三個字元陣列
(list、list2、list3),也分別給於其值(此部份請自己依所需撰寫)及兩個整數陣列(mID、mreminder)
帶入建構子中建構該元件後帶入ListView,要帶入什麼參數和參數的順序是依照規劃MyAdapter這個
BaseAdapter子類別時怎麼開的,這裡就會是需要什麼樣的參數和順序,下面貼出MyAdapter的程式碼。
package jim.memorandum;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MyAdapter extends BaseAdapter{
public LayoutInflater myInflater;
public Context context;
CharSequence[] mDate = null;
CharSequence[] mData = null;
CharSequence[] mPw = null;
int[] MID = null;
int[] mreminder = null;
public MyAdapter(Context ctxt, CharSequence[] mdate,int[] mID,CharSequence[] mdata,CharSequence[] mpw,int[] mreminder){
myInflater = LayoutInflater.from(ctxt);
this.mDate = mdate;
this.MID = mID;
this.mData = mdata;
this.context = ctxt;
this.mPw = mpw;
this.mreminder = mreminder;
}
public int getCount() {
// TODO Auto-generated method stub
return MID.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return MID[position];
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
final int index = position;
ViewTag viewTag;
if(convertView == null){
convertView = myInflater.inflate(R.layout.list_data, null);
viewTag = new ViewTag(
(TextView)convertView.findViewById(R.id.tv_Date),
(TextView)convertView.findViewById(R.id.tv_Data),
(ImageButton)convertView.findViewById(R.id.ibtn_edit),
(ImageButton)convertView.findViewById(R.id.ibtn_del),
(ImageView)convertView.findViewById(R.id.img_remind),
(ImageView)convertView.findViewById(R.id.img_lock)
);
convertView.setTag(viewTag);
}
else{
viewTag = (ViewTag) convertView.getTag();
}
//如果有設定密碼就只顯示前五個字
String stitle ="";
if(!mPw[position].toString().equalsIgnoreCase("")){
stitle = mData[position].toString();
if(stitle.length() > 3){
stitle = stitle.subSequence(0, 3) + "...";
}
else
{
stitle = mData[position].toString();
}
}
else
{
stitle = mData[position].toString();
}
viewTag.tvdata.setText(stitle);
viewTag.tvdate.setText(mDate[position].toString());
//提醒
if(mreminder[index] == 1)
{
viewTag.img_reminder.setImageResource(R.drawable.checkbox_on);
}
else
{
viewTag.img_reminder.setImageResource(R.drawable.checkbox_off);
}
//是否有密碼
if(!mPw[index].toString().equalsIgnoreCase(""))
{
viewTag.img_lock.setImageResource(R.drawable.lock_on);
}
else
{
viewTag.img_lock.setImageResource(R.drawable.lock_off);
}
//修改按鈕
final ImageButton btn_edit = (ImageButton) convertView.findViewById(R.id.ibtn_edit);
btn_edit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//有密碼時必須輸入密碼
if(!mPw[index].toString().equalsIgnoreCase(""))
{
LayoutInflater factory=LayoutInflater.from(context);
//得到自定義對話框
final View DialogView=factory.inflate(R.layout.dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("請輸入密碼");
builder.setCancelable(false);
builder.setView(DialogView); //設置自定義對話框樣式
builder.setPositiveButton("送出", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
try
{
EditText pw = (EditText)DialogView.findViewById(R.id.pw_dialog);//輸入之密碼
//驗證密碼是否相同
String sPW1 = mPw[index].toString();//原密碼
String sPW2 = pw.getText().toString();//驗證密碼
if(sPW1.equals(sPW2))
{
//相同就進入
Intent intent_request = new Intent(context, Edit.class);
String val=String.valueOf(MID[index]);
intent_request.putExtra("val", val);
context.startActivity(intent_request);
}else
{
//不相同時顯示密碼錯誤
Toast.makeText(context,"密碼錯誤!", Toast.LENGTH_SHORT).show();
}
}catch(Exception e)
{
e.printStackTrace();
}
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
}else
{
Intent intent_request = new Intent(context, Edit.class);
String val=String.valueOf(MID[index]);
intent_request.putExtra("val", val);
context.startActivity(intent_request);
}
}
});
//刪除按鈕
final ImageButton btn_del = (ImageButton) convertView.findViewById(R.id.ibtn_del);
btn_del.setTag(position);
btn_del.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("確定要刪除?");
builder.setCancelable(false);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int dialog_id) {
SQLiteDatabase db;
NewListDataSQL helper = new NewListDataSQL(context, "MemorandumSQL");
db = helper.getReadableDatabase();
long long1 = db.delete("newMemorandum", "_ID=" + MID[index], null);
//添加成功後返回行號,失敗後返回-1
if (long1 == -1) {
Toast.makeText(context,
"刪除失敗!", Toast.LENGTH_SHORT)
.show();
} else {
Intent intent = new Intent(context, MemorandumActivity.class);
context.startActivity(intent);
quit();//關閉,讓back鍵不會出現上一頁
}
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
return convertView;
}
public class ViewTag{
TextView tvdate;
TextView tvdata;
ImageButton ibtnEdit;
ImageButton ibtnDel;
ImageView img_reminder;
ImageView img_lock;
public ViewTag(TextView date, TextView data, ImageButton edit, ImageButton del, ImageView img1, ImageView img2){
this.tvdate = date;
this.tvdata = data;
this.ibtnEdit = edit;
this.ibtnDel = del;
this.img_reminder = img1;
this.img_lock = img2;
}
}
public void quit() {
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
System.exit(0);
}
}
說明:
1.MyAdapter是繼承自BaseAdapter這個子類別
2.LayoutInflater myInflater 指的是一種擴充,就是說如果你想用自定的XML配置檔
可以用此擴充把自定的XML置檔加入到現有元件中
3.Activity在建構此類別時,需要帶入什麼參數是在MyAdapter 內設定的
如果這個也不了解請麻煩去翻一下物件導向書籍
4.重點在getView內,所有的自定介面設定、處理都在getView內產生及設定、處理
5.有使用一個viewTag的元件設定類別,要告訴介面自定義的XML內有哪些元件配置
貼出自定義的XML配置檔,讓各位更了解崁在ListView內的是怎麼配置的
list_data.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:descendantFocusability="blocksDescendants"
android:background="@drawable/button_style" >
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tv_Date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="20dp" />
<ImageView
android:id="@+id/img_lock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/img_remind"
android:layout_alignParentTop="true"
android:contentDescription="@string/password"
/>
<ImageView
android:id="@+id/img_remind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/ibtn_edit"
android:layout_alignParentTop="true"
android:contentDescription="@string/remind"
/>
<ImageButton
android:id="@+id/ibtn_del"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@android:drawable/ic_menu_delete"
android:contentDescription="@string/del" />
<ImageButton
android:id="@+id/ibtn_edit"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/ibtn_del"
android:src="@android:drawable/ic_menu_edit"
android:contentDescription="@string/edit" />
</RelativeLayout>
<TextView
android:id="@+id/tv_Data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
實際圖型:
後記:
這個是ListView中的自定義圖型,當然這是有美化過的,所以看起來才會有點不一樣
不過如果你想要做到像這個樣子,就一定要用BaseAdapter,然後套用自定義XML配置檔list_data.xml
不然是做不出這樣很自由的變化配置的,以上介紹,謝謝。

我用BASEADAPTER去接收資料庫...
回覆刪除可是有三筆資料卻都只顯示同一筆..
if(cursor.moveToFirst()){
for(int i = 0;i< cursor.getCount();i++){
tag.id.setText(cursor.getString( 0));
tag.content.setText(cursor.getString(1));
cursor.moveToNext();
}
}
看你的部份程式碼問題應該是在tag
刪除你用.setText應該只能寫一筆資料
而你下一筆再用一次.setText只是把tag內的文字改掉而已
所以你用迴圈跑還只有一筆資料會進tag而已
我用的是陣列的方式,所以才會有多筆進去
往這個方向檢查及修改,應該就沒問題了