對話(huà)框介紹與示例
對話(huà)框在程序中不是必備的,但是用好對話(huà)框能對我們編寫(xiě)的應用增色不少。采用對話(huà)框可以大大增加應用的友好性。比較常用的背景是:用戶(hù)登陸、網(wǎng)絡(luò )正在下載、下載成功或者失敗的提示,還有,比如:短信來(lái)了、電池沒(méi)電了等等,只要你想到的,能提高用戶(hù)體驗的,你都可以使用對話(huà)框。
首先,請大家找到文檔,在右上角的搜索框中輸入Dialog,根據提示,選擇app.dialog。大家可以先閱讀一下英文文檔,大體先看看,繼承于哪個(gè)類(lèi),有哪些子類(lèi)等等,這對于知識的積累相當重要。不是很難,如果你覺(jué)得讀不懂,可以借助有道詞典。我一直覺(jué)得,如果沒(méi)有中國這么龐大的市場(chǎng),
Android不可能發(fā)展這么快,可是他們?yōu)槭裁淳筒怀鲋形奈臋n呢,反而出日語(yǔ)的文檔,想不通。強烈建議他們盡快出中文的文檔。
什么是Dialog
Dialog類(lèi),是一切對話(huà)框的基類(lèi),需要注意的是,Dialog類(lèi)雖然可以在界面上顯示,但是并非繼承于View類(lèi),而是直接從java.lang.Object開(kāi)始構造出的。類(lèi)似于A(yíng)ctivity,Dialog也是有生命周期的,它的生命周期由Activity來(lái)維護。Activity負責生成、保存、恢復它。在生命周期的每一個(gè)階段都有一些回調函數供系統反向調用。
ShowDialog(int id):負責顯示標示為id的Dialog,這個(gè)函數如果調用后,系統將反向調用Dialog的回調函數onCreateDialog(int id);
dismissDialog(int id):使標示為id的Dialog在界面當中消。
Dialog有兩個(gè)比較常見(jiàn)的回調函數,onCreateDialog(int id)和onPrepareDialog(int id,Dialog dialog)。如果Activity調用了showDialog(int id)后,如果這個(gè)Dialog是第一次生成,系統將反向調用Dialog的回調函數onCreateDialog(int id),再調用onPrepareDialog(int id ,Dialog dialog),如果這個(gè)Dialog還沒(méi)有生成,只不過(guò)還沒(méi)有顯示出來(lái),那么將不會(huì )回調onCreateDialog(int id),而是直接回調onPrepareDialog(int id,Dialog dialog)方法。onPrepareDialog(int id,Dialog dialog)方法提供了這樣一套機制,當Dialog生成但是沒(méi)有顯示出來(lái)的時(shí)候,使得有機會(huì )在顯示前對Dialog做一些修改,如對Dialog標題進(jìn)行修改。
什么是AlertDialog?什么是AlertDialog.Builder?
AlertDialog是Dialog的一個(gè)直接子類(lèi),一個(gè)AlertDialog可以有兩個(gè)Button或者3個(gè)Button,可以對一個(gè)AlertDialog設置title、message。不能直接通過(guò)AlertDialog的構造函數來(lái)生成一個(gè)AlertDialog,一般生成的時(shí)候都是通過(guò)它的的一個(gè)內部靜態(tài)類(lèi)AlertDialog.Builder來(lái)構造的。
下面才是我寫(xiě)這篇文章的用意,在對話(huà)框中實(shí)現自定義視圖,來(lái)提升用戶(hù)體驗。
給Dialog設置個(gè)性化的View(我翻譯為視圖)
系統中提供的太死板了,我們總是會(huì )有很多新奇的想法,那么如何實(shí)現給一個(gè)Dialog自定義一個(gè)布局呢?我們要用到LayoutInFlater,通過(guò)這個(gè)類(lèi)的inflate方法,可以將一個(gè)XML的布局變成一個(gè)View實(shí)例。這種用法,我們會(huì )經(jīng)常用到,所以務(wù)必學(xué)會(huì )。然后,我們通過(guò)builder.setView(myownview)這個(gè)語(yǔ)句,就可以將個(gè)性化的視圖放到Dialog里邊去。當然,你可以傳入任何的視圖對象,比如圖片框,WebView等,盡情發(fā)揮你的想象力吧。
進(jìn)度條Dialog:ProgressDialog
顧名思義,這個(gè)Dialog負責給用戶(hù)顯示進(jìn)度的相關(guān)情況,它是AlertDialog的一個(gè)子類(lèi),在我的示例代碼中,我是實(shí)現默認的進(jìn)度顯示。當然可以配置自己的進(jìn)度條。同時(shí)有一點(diǎn),提醒大家要注意,ProgressDialog不需要Builder這個(gè)內部靜態(tài)類(lèi)進(jìn)行構造,而是直接使用構造函數進(jìn)行構造。
其實(shí)在
android當中還提供了很多Dialog,如CharacterPickerDialog/TimePickerDialog/DatePickerDialog等,但是都不是很常用。用到的,大家就自己去查把,我暫時(shí)還用不到,因此就不給大家示例代碼了,因為我時(shí)間也非常緊,做測試的話(huà),非常費時(shí)間。如果有朋友測試了,或者正好手中有這樣的列子,可以回復我下,我加進(jìn)來(lái),以便其它的朋友查看,學(xué)習。
上面把Dialog的基礎都說(shuō)了說(shuō),說(shuō)實(shí)話(huà),懂這些還不夠,遠遠不夠,等真正開(kāi)發(fā)應用的時(shí)候,如果你用了這些,就會(huì )發(fā)現你做出的應用很難看,或者不適用。因此,做些變通還是非常必要的。
下面的圖片是第一個(gè)示例程序的代碼:有6個(gè)截圖:(示例代碼名稱(chēng):AlertDialogTest1.rar)
彈出選擇框(示例代碼名稱(chēng):AlertDialogTest.rar)
如果你用過(guò)新浪微博的anroid客戶(hù)端或者人人網(wǎng)的android客戶(hù)端,那么你就會(huì )發(fā)現,下面截圖中的效果,你是一定見(jiàn)過(guò)的,通常通過(guò)這種對話(huà)框去提示用戶(hù)做一些選擇。那么這種效果是如何實(shí)現的呢?下面做簡(jiǎn)單分析。
//注意這里千萬(wàn)不要用this.getApplicationContext(),因為只有Activity才能生成Dialog
CharSequence[] items = {"手機相冊", "手機拍照", "清除照片"};
AlertDialog imageDialog = new AlertDialog.Builder(MainActivity.this)
.setItems(items, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int item) {
}
通過(guò).setItems()就可以實(shí)現這種效果,第一個(gè)參數是一個(gè)數組,第二個(gè)參數是一個(gè)回調函數,當你點(diǎn)擊某一項時(shí)觸發(fā)的事件。
這里有一點(diǎn)要注意,我在開(kāi)始測試的時(shí)候,是這么寫(xiě)的:
AlertDialog imageDialog = new AlertDialog.Builder(this.getApplicationContext());
總是出錯,我一直想不到錯在哪里,看了錯誤才知道,WindowManager$BadTokenException: Unable to add window -- token null is not for an application。這里要寫(xiě)Activity,不能寫(xiě)this.getApplicationContext(),大家可以參考這篇文章,自然就明白是怎么回事了。
http://www.cnblogs.com/oakpip/archive/2011/04/06/2007310.htmlsetItems(items, new DialogInterface.OnClickListener()
這里我們是用這個(gè)方法設置的,如果很多怎么辦,比如說(shuō)從數據庫中取出來(lái)得怎么辦?好幾十條、甚至好幾千條也這樣做么?想一想…當然可以了,我測試過(guò)的,沒(méi)有問(wèn)題,就是很多,會(huì )有下拉條的。
其實(shí)我們還有一種方法,大家看下面。這里我通過(guò)這個(gè)方法實(shí)現的。
(參看AlertdialogTest3->MainActivity1.java)
AlertDialog可以使用自定義的layout文件。通常在界面比較復雜的情況下使用。有時(shí)候(大多數情況下),我們只是需要在alertdialog中顯示一個(gè)列表并可以對相關(guān)的事件作出操作,這時(shí)候用自定義alertdialog顯得過(guò)于復雜。用setItem可以做到這一點(diǎn),但是卻不能改變每個(gè)item的高度。這時(shí)候可以用setAdapter,在adapter中指定給item指定一個(gè)xml布局文件,然后在布局xml文件中定義相關(guān)樣式。
builder.setAdapter(new ArrayAdapter(MainActivity.this,
android.R.layout.simple_dropdown_item_1line,items), new DialogInterface.OnClickListener(){
效果和用setItems()是一樣的,這里的數據我都是用數組表示的。并沒(méi)有從數據庫取出來(lái)?又回到剛才的問(wèn)題,如果是從數據庫取出來(lái)的呢?可不可以在每一條前面加個(gè)圖標呢?在后面加一個(gè)單選按鈕呢?答案是肯定的。請看后面的介紹。
先看這種實(shí)現方法:(參看AlertdialogTest3->MainActivity2.java)
第一幅圖,只有5個(gè)值,下面還空好多,可能是布局的問(wèn)題,把框弄太大了;第二幅圖,有15個(gè)數據,當你滑動(dòng)時(shí),會(huì )有滾動(dòng)條。第三幅圖,是我在第二幅圖上單擊時(shí)的效果。我只處理了單擊事件,沒(méi)處理選擇事件。
當你在使用人人網(wǎng)的Android客戶(hù)度的時(shí)候,當你要更新?tīng)顟B(tài)的時(shí)候,你會(huì )發(fā)現這樣一個(gè)發(fā)送框,如下所示:(參看AlertdialogTest3->MainActivity3.java)
做些說(shuō)明,這是我示例代碼的效果,當點(diǎn)擊button的時(shí)候,會(huì )彈出這個(gè)對話(huà)框,你可以輸入內容,如果你沒(méi)有輸入任何內容或者輸入了很多空格,那么當你點(diǎn)擊發(fā)送后,會(huì )提示你內容不能為空;當你正確輸入內容后,會(huì )以吐絲效果顯示你發(fā)送的內容,當然這是我為了測試才這樣做的,你也可以實(shí)現你自己的想法,比如調用人人網(wǎng)的API,發(fā)送一條新鮮事什么的。
最后還要介紹一點(diǎn)東西,去除白色邊框的方法。
使用樣式文件,在values 目錄下新建styles.xml文件,編寫(xiě)如下代碼:
<resources>
<style name="dialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/black</item>
<item name="android:windowBackground">@null</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
調用時(shí),使用AlerDialog的接口類(lèi),Dialog 接口編寫(xiě)如下代碼:
Dialog dialog = new Dialog(SetActivity.this, R.style.dialog);
dialog.setContentView(R.layout.test);
dialog.show();
下面我們查看一下Dialog的源碼文件,里面的構造函數為如下:
public Dialog(Context context, int theme) {
mContext = new ContextThemeWrapper(
context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);
mWindowManager = (WindowManager)context.getSystemService("window");
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mUiThread = Thread.currentThread();
mDismissCancelHandler = new DismissCancelHandler(this);
}
這里面我們可以看出,Android 使用了默認的構造函數為Dialog 設置樣式,如果沒(méi)有為其設置樣式,即默認加載事先編寫(xiě)好的樣式文件,Dialog 一共由多個(gè)9.png的圖片構成,大部分都是帶有邊框的9.png圖片,所以就是為什么我們上邊的樣式文件要將其背景去除掉。這個(gè)東西搞了我好久,希望對你有幫助。
前后效果對比
未設置前:
設置后:
下面的東西轉自一個(gè)網(wǎng)友的文章,大家再看看,印象就更深了。
創(chuàng )建對話(huà)框
一個(gè)對話(huà)框一般是一個(gè)出現在當前Activity之上的一個(gè)小窗口. 處于下面的Activity失去焦點(diǎn), 對話(huà)框接受所有的用戶(hù)交互. 對話(huà)框一般用于提示信息和與當前應用程序直接相關(guān)的小功能.
Android API 支持下列類(lèi)型的對話(huà)框對象:
警告對話(huà)框 AlertDialog: 一個(gè)可以有0到3個(gè)按鈕, 一個(gè)單選框或復選框的列表的對話(huà)框. 警告對話(huà)框可以創(chuàng )建大多數的交互界面, 是推薦的類(lèi)型.
進(jìn)度對話(huà)框 ProgressDialog: 顯示一個(gè)進(jìn)度環(huán)或者一個(gè)進(jìn)度條. 由于它是AlertDialog的擴展, 所以它也支持按鈕.
日期選擇對話(huà)框 DatePickerDialog: 讓用戶(hù)選擇一個(gè)日期.
時(shí)間選擇對話(huà)框 TimePickerDialog: 讓用戶(hù)選擇一個(gè)時(shí)間.
如果你希望自定義你的對話(huà)框, 可以擴展Dialog類(lèi).
Showing a Dialog 顯示對話(huà)框
一個(gè)對話(huà)框總是被創(chuàng )建和顯示為一個(gè)Activity的一部分. 你應該在A(yíng)ctivity的onCreateDialog(int)中創(chuàng )建對話(huà)框. 當你使用這個(gè)回調函數時(shí),Android系統自動(dòng)管理每個(gè)對話(huà)框的狀態(tài)并將它們和Activity連接, 將Activity變?yōu)閷υ?huà)框的"所有者". 這樣,每個(gè)對話(huà)框從Activity繼承一些屬性. 例如,當一個(gè)對話(huà)框打開(kāi)時(shí), MENU鍵會(huì )顯示Activity的菜單, 音量鍵會(huì )調整Activity當前使用的音頻流的音量.
注意: 如果你希望在onCreateDialog()方法之外創(chuàng )建對話(huà)框, 它將不會(huì )依附在A(yíng)ctivity上. 你可以使用setOwnerActivity(Activity)來(lái)將它依附在A(yíng)ctivity上.
當你希望顯示一個(gè)對話(huà)框時(shí), 調用showDialog(int)并將對話(huà)框的id傳給它.
當一個(gè)對話(huà)框第一次被請求時(shí),Android調用onCreateDialog(int). 這里是你初始化對話(huà)框的地方. 這個(gè)回調函數傳入的id和showDialog(int)相同. 創(chuàng )建對話(huà)框之后,將返回被創(chuàng )建的對象.
在對話(huà)框被顯示之前,Android還會(huì )調用onPrepareDialog(int, Dialog). 如果你希望每次顯示對話(huà)框時(shí)有動(dòng)態(tài)更改的內容, 那么就改寫(xiě)這個(gè)函數. 該函數在每次一個(gè)對話(huà)框打開(kāi)時(shí)都調用. 如果你不定義該函數,則對話(huà)框每次打開(kāi)都是一樣的. 該函數也會(huì )傳入對話(huà)框的id以及你在onCreateDialog()中創(chuàng )建的Dialog對象.
最好的定義onCreateDialog(int) 和onPrepareDialog(int, Dialog) 的方法就是使用一個(gè)switch語(yǔ)句來(lái)檢查傳入的id. 每個(gè)case創(chuàng )建相應的對話(huà)框. 例如, 一個(gè)游戲使用兩個(gè)對話(huà)框: 一個(gè)來(lái)指示游戲暫停,另一個(gè)指示游戲結束. 首先, 為它們定義ID:static final int DIALOG_PAUSED_ID = 0;
static final int DIALOG_GAMEOVER_ID = 1;
然后, 在onCreateDialog(int)中加入一個(gè)switch語(yǔ)句:
protected Dialog onCreateDialog(int id) {
Dialog dialog;
switch(id) {
case DIALOG_PAUSED_ID:
// do the work to define the pause Dialog
break;
case DIALOG_GAMEOVER_ID:
// do the work to define the game over Dialog
break;
default:
dialog = null;
}
return dialog;
}
注意: 在這個(gè)例子中, case語(yǔ)句為空因為定義Dialog的程序在后面會(huì )有介紹.
在需要顯示對話(huà)框是, 調用showDialog(int), 傳入對話(huà)框的id:
showDialog(DIALOG_PAUSED_ID);Dismissing a Dialog 解除對話(huà)框
當你準備關(guān)閉對話(huà)框時(shí), 你可以使用dismiss()函數. 如果需要的話(huà), 你也可以從Activity調用dismissDialog(int), 二者效果是一樣的.
如果你使用onCreateDialog(int)來(lái)管理你的對話(huà)框的狀態(tài), 那么每次你的對話(huà)框被解除時(shí), 該對話(huà)框對象的狀態(tài)會(huì )被Activity保存. 如果你決定你不再需要這個(gè)對象或者需要清除對話(huà)框的狀態(tài), 那么你應該調用 removeDialog(int). 這將把所有該對象的內部引用移除, 如果該對話(huà)框在顯示的話(huà)將被解除.
Using dismiss listeners 使用解除監聽(tīng)器
如果你希望在對話(huà)框解除時(shí)運行某些程序, 那么你應該給對話(huà)框附加一個(gè)解除監聽(tīng)器.
首先定義DialogInterface.OnDismissListener接口. 這個(gè)接口只有一個(gè)方法, onDismiss(DialogInterface), 該方法將在對話(huà)框解除時(shí)被調用.
然后將你的OnDismissListener實(shí)現傳給setOnDismissListener().
然而,注意對話(huà)框也可以被"取消". 這是一個(gè)特殊的情形, 它意味著(zhù)對話(huà)框被用戶(hù)顯式的取消掉. 這將在用戶(hù)按下"back"鍵時(shí), 或者對話(huà)框顯式的調用cancel()(按下對話(huà)框的cancel按鈕)時(shí)發(fā)生. 當一個(gè)對話(huà)框被取消時(shí), OnDismissListener將仍然被通知, 但如果你希望在對話(huà)框被顯示取消(而不是正常解除)時(shí)被通知, 則你應該使用setOnCancelListener()注冊一個(gè)DialogInterface.OnCancelListener.
Creating an AlertDialog 創(chuàng )建警告對話(huà)框
An AlertDialog is an extension of the Dialog class. It is capable of constructing most dialog user interfaces and is the suggested dialog type. You should use it for dialogs that use any of the following features:
一個(gè)警告對話(huà)框是對話(huà)框的一個(gè)擴展. 它能夠創(chuàng )建大多數對話(huà)框用戶(hù)界面并且是推薦的對話(huà)框類(lèi)新星. 對于需要下列任何特性的對話(huà)框,你都應該使用它:
一個(gè)標題
一條文字消息
1個(gè)-3個(gè)按鈕
一個(gè)可選擇的列表(單選框或者復選框)
要創(chuàng )建一個(gè)AlertDialog, 使用AlertDialog.Builder子類(lèi). 使用AlertDialog.Builder(Context)來(lái)得到一個(gè)Builder, 然后使用該類(lèi)的公有方法來(lái)定義AlertDialog的屬性. 設定好以后, 使用create()方法來(lái)獲得AlertDialog對象.
下面的主題展示了如何為AlertDialog定義不同的屬性, 使用AlertDialog.Builder類(lèi). 如果你使用這些示例代碼, 你可以在onCreateDialog()中返回最后的Dialog對象來(lái)獲得圖片中對話(huà)框的效果.
Adding buttons 增加按鈕
要創(chuàng )建一個(gè)如圖所示的窗口, 使用set...Button()方法:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MyActivity.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
首先,使用setMessage(CharSequence)為對話(huà)框增加一條消息。 然后, 開(kāi)始連續調用方法, 使用setCancelable(boolean)將對話(huà)框設為不可取消(不能使用back鍵來(lái)取消)。對每一個(gè)按鈕,使用set...Button() 方法,該方法接受按鈕名稱(chēng)和一個(gè)DialogInterface.OnClickListener,該監聽(tīng)器定義了當用戶(hù)選擇該按鈕時(shí)應做的動(dòng)作。
注意:對每種按鈕類(lèi)型,只能為AlertDialog創(chuàng )建一個(gè)。也就是說(shuō),一個(gè)AlertDialog不能有兩個(gè)以上的"positive"按鈕。這使得可能的按鈕數量最多為三個(gè):肯定、否定、中性。這些名字和實(shí)際功能沒(méi)有聯(lián)系,但是將幫助你記憶它們各做什么事情。Adding a list 增加列表
要創(chuàng )建一個(gè)具有可選項的AlertDialog,使用setItems()方法:
final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert = builder.create();
首先增加一個(gè)標題。然后使用setItems()增加一個(gè)可選列表,該列表接受一個(gè)選項名稱(chēng)的列表和一個(gè)DialogInterface.OnClickListener, 后者定義了選項對應的響應。
Adding checkboxes and radio buttons 增加單選框和復選框
要創(chuàng )建一個(gè)帶有多選列表或者單選列表的對話(huà)框, 使用setMultiChoiceItems()和setSingleChoiceItems()方法。如果你在onCreateDialog()中創(chuàng )建可選擇列表, Android會(huì )自動(dòng)管理列表的狀態(tài). 只要activity仍然活躍, 那么對話(huà)框就會(huì )記住剛才選中的選項,但當用戶(hù)退出activity時(shí),該選擇丟失。
注意: 要在你的acitivity離開(kāi)和暫停時(shí)保存選擇, 你必須在activity的聲明周期中正確的保存和恢復設置。為了永久性保存選擇,你必須使用數據存儲技術(shù)中的一種。
要創(chuàng )建一個(gè)具有單選列表的AlertDialog,只需將一個(gè)例子中的setItems()換成 setSingleChoiceItems():final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert = builder.create();
第二個(gè)參數是默認被選中的選項位置,使用“-1”來(lái)表示默認情況下不選中任何選項。
Creating a ProgressDialog 創(chuàng )建進(jìn)度對話(huà)框
一個(gè)ProgressDialog(進(jìn)度對話(huà)框)是AlertDialog的擴展。它可以顯示一個(gè)進(jìn)度的動(dòng)畫(huà)——進(jìn)度環(huán)或者進(jìn)度條。這個(gè)對話(huà)框也可以提供按鈕,例如取消一個(gè)下載等。
打開(kāi)一個(gè)進(jìn)度對話(huà)框很簡(jiǎn)單,只需要調用 ProgressDialog.show()即可。例如,上圖的對話(huà)框可以不通過(guò)onCreateDialog(int),而直接顯示:
ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",
"Loading. Please wait...", true);
第一個(gè)參數是應用程序上下文。第二個(gè)為對話(huà)框的標題(這里為空),第三個(gè)為對話(huà)框內容, 最后一個(gè)為該進(jìn)度是否為不可確定的(這只跟進(jìn)度條的創(chuàng )建有關(guān),見(jiàn)下一節)。
進(jìn)度對話(huà)框的默認樣式為一個(gè)旋轉的環(huán)。如果你希望顯示進(jìn)度值,請看下一節。
Showing a progress bar 顯示進(jìn)度條
使用一個(gè)動(dòng)畫(huà)進(jìn)度條來(lái)顯示進(jìn)度:
使用 ProgressDialog(Context)構造函數來(lái)初始化一個(gè)ProgressDialog對象。
將進(jìn)度樣式設置為"STYLE_HORIZONTAL",使用setProgressStyle(int)方法。并且設置其它屬性,例如內容等。
在需要顯示時(shí)調用show()或者從onCreateDialog(int)回調函數中返回該ProgressDialog。
你可以使用 setProgress(int)或者incrementProgressBy(int)來(lái)增加顯示的進(jìn)度。
例如,你的設置可能像這樣:ProgressDialog progressDialog;
progressDialog = new ProgressDialog(mContext);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
設置很簡(jiǎn)單。大部分創(chuàng )建進(jìn)度對話(huà)框需要的代碼是在更新它的進(jìn)程中。你可能需要在一個(gè)新的線(xiàn)程中更新它,并使用Handler來(lái)將進(jìn)度報告給Activity。如果你不熟悉使用Handler和另外的線(xiàn)程,請看下列例子,該例子使用了一個(gè)新的線(xiàn)程來(lái)更新進(jìn)度。
Example ProgressDialog with a second thread 例--使用一個(gè)線(xiàn)程來(lái)顯示進(jìn)度對話(huà)框
這個(gè)例子使用一個(gè)線(xiàn)程來(lái)跟蹤一個(gè)進(jìn)程的進(jìn)度(其實(shí)為從1數到100)。每當進(jìn)度更新時(shí),該線(xiàn)程通過(guò)Handler給主activity發(fā)送一個(gè)消息。主 Activity更新ProgressDialog.package com.example.progressdialog;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class NotificationTest extends Activity {
static final int PROGRESS_DIALOG = 0;
Button button;
ProgressThread progressThread;
ProgressDialog progressDialog;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Setup the button that starts the progress dialog
button = (Button) findViewById(R.id.progressDialog);
button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
showDialog(PROGRESS_DIALOG);
}
});
}
protected Dialog onCreateDialog(int id) {
switch(id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(NotificationTest.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressThread = new ProgressThread(handler);
progressThread.start();
return progressDialog;
default:
return null;
}
}
// Define the Handler that receives messages from the thread and update the progress
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
int total = msg.getData().getInt("total");
progressDialog.setProgress(total);
if (total >= 100){
dismissDialog(PROGRESS_DIALOG);
progressThread.setState(ProgressThread.STATE_DONE);
}
}
};
/** Nested class that performs progress calculations (counting) */
private class ProgressThread extends Thread {
Handler mHandler;
final static int STATE_DONE = 0;
final static int STATE_RUNNING = 1;
int mState;
int total;
ProgressThread(Handler h) {
mHandler = h;
}
public void run() {
mState = STATE_RUNNING;
total = 0;
while (mState == STATE_RUNNING) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Log.e("ERROR", "Thread Interrupted");
}
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", total);
msg.setData(b);
mHandler.sendMessage(msg);
total++;
}
}
/* sets the current state for the thread,
* used to stop the thread */
public void setState(int state) {
mState = state;
}
}
}
Creating a Custom Dialog 創(chuàng )建自定義對話(huà)框
如果你想自定義一個(gè)對話(huà)框,你可以使用布局元素來(lái)創(chuàng )造你的對話(huà)框的布局。定義好布局后,將根View對象或者布局資源ID傳給setContentView(View).
例如,創(chuàng )建如圖所示的對話(huà)框:
創(chuàng )建一個(gè)xml布局custom_dialog.xml:
http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFF"
/>
該xml定義了一個(gè)LinearLayout中的一個(gè)ImageView 和一個(gè)TextView。
將以上布局設為對話(huà)框的content view,并且定義ImageView 和 TextView的內容:
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
在初始化Dialog之后,使用setContentView(int),將布局資源id傳給它?,F在Dialog有一個(gè)定義好的布局,你可以使用findViewById(int)來(lái)找到該元素的id并修改它的內容。
使用前面所講的方法顯示對話(huà)框。
一個(gè)使用Dialog類(lèi)建立的對話(huà)框必須有一個(gè)標題。如果你不調用setTitle(),那么標題區域會(huì )保留空白。如果你不希望有一個(gè)標題,那么你應該使用AlertDialog類(lèi)來(lái)創(chuàng )建自定義對話(huà)框。然而,由于一個(gè)AlertDialog使用AlertDialog.Builder類(lèi)來(lái)建立最方便,所以你沒(méi)有方法使用setContentView(int),而是只能使用setView(View)。該方法接受一個(gè)View對象,所以你需要從xml中展開(kāi)你的根View。
要展開(kāi)一個(gè)xml布局,使用 getLayoutInflater() (或 getSystemService())取得LayoutInflater,然后調用inflate(int, ViewGroup),第一個(gè)參數為布局id,而第二個(gè)參數為根view的id?,F在,你可以使用展開(kāi)后的布局來(lái)找到View對象并定義 ImageView和TextView元素的內容。然后實(shí)例化AlertDialog.Builder并使用setView(View)來(lái)為對話(huà)框設置展開(kāi)后的布局。例如:
AlertDialog.Builder builder;
AlertDialog alertDialog;
Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog,
(ViewGroup) findViewById(R.id.layout_root));
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();
使用AlertDialog來(lái)自定義對話(huà)框,可以利用其內置特性例如按鈕、選擇列表、標題、圖標等。