幾乎元件在使用自定義的方式呈現時最常出現的一個子類別
因為自定義的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而已
我用的是陣列的方式,所以才會有多筆進去
往這個方向檢查及修改,應該就沒問題了