轉自:http://android.blog.51cto.com/268543/333769/
本文是對網上的文章《Android開發指南-用戶界面-對話框》的部分內容進行簡化,并加上自己的某些理解。里面的相同內容,版權歸原翻譯作者所有。
顯示對話框
對話框經常作為Activity的一部分來創建和顯示。你通常應該從protected Dialog?Activity.onCreateDialog (int id)回調方法里創建對話框。當你使用這個回調函數時,Android系統會有效的設置這個Activity為每個對話框的所有者,從而自動管理每個對話框的狀態并掛靠到Activity上。這樣,每個對話框繼承這個Activity的特定屬性。比如,當一個對話框打開時,菜單鍵顯示為這個Activity定義的選項菜單,音量鍵修改Activity使用的音頻流。
注意:?如果你決定在onCreateDialog()方法之外創建一個對話框,它將不會被附著到活動上。不過,你可以通過setOwnerActivity(Activity)把它附著到一個活動上。
當你想要顯示一個對話框時,調用showDialog(int id)方法并傳遞一個唯一標識這個對話框的整數。
當對話框第一次被請求時,Android從你的Activity中調用onCreateDialog(int id),你應該在這里初始化這個對話框Dialog。這個回調方法被傳以和showDialog(int id)相同的ID。當你創建這個對話框后,在Activity的最后返回這個對象。
在對話框被顯示之前,Android還調用了可選的回調函數onPrepareDialog(int id, Dialog). 如果你想在每一次對話框被打開時改變它的任何屬性,你可以定義這個方法。這個方法在每次打開對話框時被調用,而onCreateDialog(int) 僅在對話框第一次打開時被調用。如果你不定義onPrepareDialog(),那么這個對話框將保持和上次打開時一樣。這個方法也被傳遞以對話框的ID,和在onCreateDialog()中創建的對話框對象。(個人理解是,在本Activity里第一次show某個Dialog,則先調用onCreateDialog,得到返回的Dialog對象并掛靠在Activity,保存Dialog對象的引用,然后才顯示Dialog。這樣子,下次再show Dialog就不用重新創建Dialog對象,而是重用舊的)
定義onCreateDialog(int)和onPrepareDialog(int, Dialog)回調函數的最佳方法是使用一個switch 語句來檢查傳遞進來的id 參數。每個case 應該檢查一個唯一的對話框ID然后創建和定義相應的對話框。比如,想象一下一個游戲使用兩個不同的對話框:一個用來指示這個游戲已經暫停而另一個來指示游戲結束。首先,為每個對話框定義一個常量:
staticfinalintDIALOG_PAUSED_ID?=0;
staticfinalintDIALOG_GAMEOVER_ID?=1;
然后,為每一個ID用一個switch case定義這個onCreateDialog(int) 回調函數:
protectedDialog?onCreateDialog(intid)?{
Dialog?dialog;
switch(id)?{
caseDIALOG_PAUSED_ID:
//?do?the?work?to?define?the?pause?Dialog
break;
caseDIALOG_GAMEOVER_ID:
//?do?the?work?to?define?the?game?over?Dialog
break;
default:
dialog?=null;
}
returndialog;
}
當是時候顯示其中之一的對話框時,使用對話框ID調用showDialog(int):
showDialog(DIALOG_PAUSED_ID);
消除對話框Dismissing a Dialog
當你準備關閉對話框時,你可以通過對這個對話框調用dismiss()來消除它。如果需要,你還可以從這個Activity中調用dismissDialog(int id)方法,這實際上將為你對這個對話框調用dismiss() 方法。
如果你想使用onCreateDialog(int id)方法來管理你對話框的狀態(就如同在前面的章節討論的那樣),然后每次你的對話框消除的時候,這個對話框對象的狀態將由該Activity保留。如果你決定不再需要這個對象或者清除該狀態是重要的,那么你應該調用removeDialog(int id)。這將刪除任何內部對象引用而且如果這個對話框正在顯示,它將被消除。
使用消除偵聽器Using dismiss listeners
如果你希望你的應用程序在一個對話框消亡的時候執行一些流程,那么你應該附著一個on-dismiss偵聽器到對話框上。
@Override
protectedvoidonPrepareDialog(intid,?Dialog?dialog)?{
switch(id){
casePROGRESS_DIALOG:
dialog.setOnDismissListener(newDialogInterface.OnDismissListener(){
@Override
publicvoidonDismiss(DialogInterface?dialog){
Toast.makeText(getApplicationContext(),
"dismiss?listener!",
Toast.LENGTH_SHORT)
.show();
}
});
}
}
然而, 請注意對話框也可以被“取消”。這是一個表明對話框被用戶顯示取消的特殊情況。這將在用戶按“返回”按鈕時發生,或者這個對話框顯示的調用cancel()(也許通過對話框上的一個“取消”按鈕)。當一個對話框被取消時,這個OnDismissListener 依然會被通知到,但是如果你希望在對話框被顯示取消時被通知到(而不是通常的消除方式),那么你應該通過setOnCancelListener()注冊一個DialogInterface.OnCancelListener。
目前個人學習發現,一般情況下,調用dialog.cancel()就會觸發onCancelLister。而點擊AlertDialog的NegativeButton (Cancel/No)是不會觸發的。對于setOnCancelListener()要注意的是,這里有兩個setOnCancelListener(),但返回值不同:
//AlertDialog.Builder調用的
publicAlertDialog.Builder?setOnCancelListener?(DialogInterface.OnCancelListener?onCancelListener)
//Dialog調用的
publicvoidsetOnCancelListener?(DialogInterface.OnCancelListener?listener)
警告對話框AlertDialog的使用
為了創建一個警告對話框,使用AlertDialog.Builder子類。通過AlertDialog.Builder(Context)獲取一個構造器然后使用這個類的公共方法來定義警告對話框的所有屬性。當得到構造器后,通過create().方法來獲取警告對話框對象。有時我是不調用create()的,而是在設置好了后直接調用show()顯示AlertDialog。
增加按鈕Adding buttons
這就是我一開始很想知道的究竟如何添加Yes/No,Ok/Cancel這樣的按鈕。原來是通過setPositiveButton(...)響應Yes/Ok的點擊,setNeutralButton(...)響應中立行為的點擊,setNegativeButton(...)響應No/Cancel的點擊。注意,只能各自設置一個按鈕來響應點擊事件。
AlertDialog.Builder?builder?=newAlertDialog.Builder(this);
builder.setMessage("Are?you?sure?you?want?to?exit?")
.setCancelable(false)
.setPositiveButton("Yes",newDialogInterface.OnClickListener()?{
publicvoidonClick(DialogInterface?dialog,intid)?{
MyActivity.this.finish();
}
})
.setNegativeButton("No",newDialogInterface.OnClickListener()?{
publicvoidonClick(DialogInterface?dialog,intid)?{
dialog.cancel();
}
});
AlertDialog?alert?=?builder.create();
首先,為這個對話框添加一個消息setMessage(CharSequence)。然后,開始函數鏈并設置該對話框為不能取消not cancelable (因此用戶不能使用返回按鈕關閉這個對話框)。對每個按鈕,使用任一set...Button() 方法,比如setPositiveButton(),該方法接受按鈕名稱以及一個定義用戶選中按鈕后所采取動作的DialogInterface.OnClickListener。
增加一個列表Adding a list
finalCharSequence[]?items?=?{"Red","Green","Blue"};
AlertDialog.Builder?builder?=newAlertDialog.Builder(this);
builder.setTitle("Pick?a?color");
builder.setItems(items,newDialogInterface.OnClickListener()?{
publicvoidonClick(DialogInterface?dialog,intitem)?{
Toast.makeText(getApplicationContext(),?items[item],?Toast.LENGTH_SHORT).show();
}
});
AlertDialog?alert?=?builder.create();
首先,用setTitle(CharSequence)方法給對話框添加一個標題。然后,添加用setItems()添加一個可選項列表,該列表接受一組顯示的items和一個DialogInterface.OnClickListener 來定義用戶選中按鈕后所采取動作。
增加復選框和單選按鈕
要在對話框里創建一個多選項列表(checkboxes)或者單選項(radio buttons),可分別調用setMultiChoiceItems()和setSingleChoiceItems()方法。如果你在onCreateDialog()回調函數中創建這些可選列表,Android會幫你管理列表狀態。只要這個活動是激活的,對話框會記住之前選中的items,但如果用戶退出這個活動,用戶選擇將丟失。
注意: 為了在用戶離開或暫停這個活動的時候能夠保存選擇,你必須通過活動生命期Activity Lifecycle來恰當的保存和恢復設置。為了永久保存選項,即使活動進程被完全終止,你需要使用數據存儲Data Storage技術。
finalCharSequence[]?items?=?{"Red","Green","Blue"};
AlertDialog.Builder?builder?=newAlertDialog.Builder(this);
builder.setTitle("Pick?a?color");
builder.setSingleChoiceItems(items,?-1,newDialogInterface.OnClickListener()?{
publicvoidonClick(DialogInterface?dialog,intitem)?{
Toast.makeText(getApplicationContext(),?items[item],?Toast.LENGTH_SHORT).show();
}
});
AlertDialog?alert?=?builder.create();
setSingleChoiceItems()的第二個參數是一個checkedItem整型數值,指示了基于0的缺省選擇項的位置。“-1”代表不會有默認選擇項。
進度對話框Progress Dialog的使用
ProgressDialog是AlertDialog類的一個擴展,可以為一個未定義進度的任務顯示一個旋轉輪形狀的進度動畫,或者為一個指定進度的任務顯示一個進度條。
可以簡單地通過調用ProgressDialog.show()方法來顯示一個進度對話框,而通過onCreateDialog(int)回調管理這個對話框是可選的,如下所示:
ProgressDialog.show(this,//?context
"",//?title
"Loading.?Please?wait...",//?message
true);//進度是否是不確定的,這只和創建進度條有關
進度對話框的缺省類型是一個旋轉輪,運行看到的是以下效果:
由于ProgressDialog是AlertDialog的擴展類,所以ProgressDialog也能設置按鈕,比如一個取消下載的按鈕。不過要注意的是,和前面的AlertDialog.Builder不同,ProgressDialog是調用AlertDialog的setButton,setButton2,setButton3函數,這些函數沒有明確哪個是正面/中立/負面的,由我們決定。
顯示進度條Showing a progress bar
而選擇動畫進度條顯示進度:
1. ? 用類構造器初始化進度對話框,ProgressDialog(Context)。
2. ? 用setProgressStyle(int)方法設置進度風格為"STYLE_HORIZONTAL"以及設置其它屬性,比如消息。
創建ProgressDialog大概是這樣的:
ProgressDialog?progressDialog?=newProgressDialog(getApplicationContext());
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setIcon(R.drawable.alert_dialog_icon);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
3. ? 當你準備顯示這個對話框時,調用show()或者從onCreateDialog(int)回調中返回ProgressDialog。
4. ? 你可以通過調用setProgress(int)設置當前進度百分比或者調用incrementProgressBy(int)方法增加進度值。
官方文檔提供了如何在另一線程來跟蹤進程進度,讓進度值變化。對此可以參考http://androidappdocs.appspot.com/guide/topics/ui/dialogs.html里面的代碼。也可以查看后面的文章《有關Android線程的學習》里面的例子,看看如何使用Handler, Message機制!
創建自定義對話框Creating a Custom Dialog
創建自定義對話框,首先要創建一個Layout xml 文件,在此不啰嗦了。然后加載Layout有兩種方法,也是非常熟悉的那兩種方法:
1.?setContentView(int resources id)
2. 利用LayoutInflater加載
官方還提示我們,一般使用Dialog類來創建對話框,是需要setTitle的,不設置的話,標題占用的空間保持為空,但仍然可見。而不想要那個標題,那應該使用警告對話框AlertDialog來創建自定義對話框。然而,因為警告對話框可以很簡單的通過AlertDialog.Builder類來創建,你并不需要訪問上面使用的setContentView(int) 方法。相反,你必須使用setView(View),則需要使用LayoutInflater來加載Layout得到View。
具體代碼參考http://androidappdocs.appspot.com/guide/topics/ui/dialogs.html