Android UI- 对话框 (AlertDialog & ProgressDialog)

转自: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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容