一个Dialog通常是一个出现在当前activity上面的一个小窗口。它下面的activity失去焦点而Dialog接受所有和用户之间的交互。Dialog通常被用做打断用户然后显示一个直接关系到当前应用的简短任务的提醒。(例如一个进度条或者是一个登录提示)
Dialog类是创建dialog的基类。然而,你通常不需要直接实力化一个dialog。相反,你应该尽量使用下面的一个子类:
AlertDialog:
一个能够管理1,2,或者3个按钮的dialog,或者是一个能够包含checkboxes或者radio buttons的可选择items的列表。AlertDialog是一个可以创建很多用户界面的dialog,而且也建议使用AlertDialog。可以参考下面的创建一个AlertDialog。
ProgressDialog:
用来显示一个progress wheel 或者 progress bar的dialog。因为它是AlertDialog的扩展,所以它也支持按钮功能。可以参考下面的创建一个ProgressDialog。
DatePickerDialog:
一个允许用户选择日期的dialog。
TimePickerDialog:
一个允许用户选择时间的dialog。
----------------------------------------------------------------------------------------------------------------------------------------------------------
显示一个dialog
一个dialog经常被作为一个activity的一部分创建和显示。你通常应该同过你的Activity的 onCreateDialog(int id)回掉方法创建dialogs。当你使用这个回掉方法时,android system将会自动的管理每一个dialog的状态,并把他们和activity联系在一起,更有效率的为每个dialog安排“owner”。这样,每一个dialog从activity中继承指定的属性。例如,当一个dialog显示的时候,menu键会显示这个activity已经定义的可选menu,音量键可以改变这个activity的音量。
注:如果你不用onCreateDialog(int)回掉方法创建dialogs,它不会绑定到任何的activity上,然而,你能通过setOwnerActivity(Activity)方法把它绑定到一个activity上。
当你想让一个dialog显示的时候,调用showDialog(int id),然后给它传递一个唯一可以标识你想显示的dialog的整数值。
当一个dialog第一次被调用的时候,android会在你的activity中调用 你实力化dialogs的onCreateDialog(int id)方法。这个回掉方法会把你传递给showDialog(int id)的id传递给它。你创建dialog后,在这个方法的最后返回这个对象。
在dialog显示之前,android也会调用可选的onPrepareDialog(int id, Dialog dialog)回调方法。如果你想每次调用dialogs时改变它的属性你可以重新定义这个方法。每次显示dialogs时都会调用这个方法,然而,onCreateDialog(int id)方法只会在第一次调用dialogs时被调用。如果你不重新定义onPrepareDialog(int id, Dialog dialog)回调方法,dialogs将会和它第一次北调用时一样。这个方法也会传递一个和你在创建Dialog对象的onCreateDialog(int id)方法一样的参数——id。
定义onCreateDialog(int id)和onPrepareDialog(int id, Dialog dialog)回调方法最好的方法是用一个switch语句来区分传递给这个方法的id参数。每一个分支应该是一个独一无二的dialog的id,然后创建和定义各自的dialog。例如,假设一个游戏用了两个不同的dialog:一个用来指示游戏停止,一个用来指示游戏结束。首先为每一个dialog定义一个整数型id:
然后在onCreateDialog(int id)方法里用一个switch分支为每一个id定义dialog的回调方法:
注:在这个例子中,在分支语句里并没有任何的代码,这是因为通常定义你的dialog的做法是在这个部分的外面。看下面关于创建一个AlertDialog部分,那里将会给出对于这个例子比较合适的代码。
当需要显示其中的一个dialog时,可以通过指定一个dialog的id来调用showDialog(int id)方法。
----------------------------------------------------------------------------------------------------------------------------------------------------------
取消一个dialog
当你准备关掉你的dialog时,你可以通过调用这个dialog对象的dismiss()方法来取消它。如果需要,你也可以从activity中调用dismissDialog(int id)方法,它的效果和调用dismiss()是一样的。
如果你是用onCreateDialog(int)回掉方法来管理你的dialog的状态(前面的部分已经讨论过了),每次当你的dialog取消时,你的dialog的状态都会被activity保存下来。如果你决定永远不再需要这个dialog对象,或者是清除这个dialog的状态是十分重要的时候,这时你可以调用removeDialog(int id)方法。这个方法将会清除这个dialog对象任何的内部引用,如果这个dialog对象是显示着的,那么这个dialog对象将会被取消。
使用取消监听器
如果你喜欢当你的dialog取消的时候做一些事情,那么你应该绑定一个取消监听器到你的dialog。
首先定义DialogInterface.OnDismissListener接口。这个接口只有一个方法——onDismiss(DialogInterface dialog),当dialog取消的时候被调用。仅仅需要传递你实现了的OnDismissListener接口到setOnDismissListener()方法。
然而,注意dialog仍然能被取消掉。这是一个特殊的情况,这个dialog被用户明确的取消了。这种情况当用户点击back键的时候会发生,或者如果这个dialog明确的调用了cancel()方法(可能是dialog中的cancel按钮)。当一个dialog被取消的时候,OnDismissListener仍然会被通知,但是如果你希望你的dialog只有当被明确的cancel时才得到通知(而不是正常的取消时),你应该在setOnCancelListener()方法中注册一个DialogInterface.OnCancelListener监听器。
----------------------------------------------------------------------------------------------------------------------------------------------------------
创建一个AlertDialog
AlertDialog是dialog类的扩展。它可以创建很多种用户界面的dialog,也建议使用这种dialog。你可以通过下面它的任何一种功能来使用它:
1)标题
2)文本信息
3)一个,两个或者三个按钮
4)一个可以选择的item的列表(带有复选框或者是单选按钮的)
你可以通过AlertDialog.Builder子类来创建一个AlertDialog对象。通过AlertDialog.Builder(Context context)来得到一个builder,然后用这个类的公共的方法去定义所有的AlertDialog的属性。当你完成了对AlertDialog的定义,通过onCreate()方法得到这个AlertDialog对象。
下面的内容介绍了如何通过AlertDialog.Builder子类来定义一个具有多个属性的AlertDialog对象。如果你在onCreateDialog(int)回掉方法中使用了下面任何一个示例代码,你会返回一个Dialog对象来显示它。
添加按钮
创建一个两边各有一个按钮的AlertDialog对象,像下面的图片一样:
可以使用set...Button()方法:
首先,通过setMessage(CharSequence char)方法为dialog添加一条信息。然后,通过追加方法的方式用setCancelable(boolean b)方法来设置dialog不能被取消(所以用户不能通过返回键取消dialog)。对于每一个button,可以使用set...Button()方法中的一种方法,例如 setPositiveButton(),它会接受一个为这个button设置名字的参数,和定义一个用户选择了这个button时所要执行的行为的DialogInterface.OnClickListener的参数。
注:对于AlertDialog每一种button类型仅仅可以添加一次。意思是说,你不可以添加多于一个的"positive"button。这里只可以添加三个button:确定按钮,中性按钮,取消按钮。这些名字严格的说和你的按钮的功能没有关系,但是它应该可以帮助你追踪哪个按钮做了什么。
添加列表
创建一个带有可选择的item列表的AlertDialog,像下面的图片一样:
使用setItem()方法:
首先,通过setTitle(CharSequence)方法为这个dialog设置标题。然后,通过setItems()方法添加一个可以选择的item的列表,它接受一个用来显示items的数组和一个当用户选择每一个item时应做的行为的 DialogInterface.OnClickListener。
添加复选框和单选按钮
分别用setMultiChoiceItems() 方法和 setSingleChoiceItems()方法创建一个带有复选框items和单选按钮items的dialog。如果你在 onCreateDialog()回调方法中创建了上面的任何一种dialog,android会帮助你管理列表中item的状态。当activity处于活动状态,dialog会记住items的原始的选择状态,但是如果用户退出了activity,选择也就消失了。
注:为了当用户离开或是暂停activity时保存选择的状态,你必须适当的在activity的生命周期中保存和重载这些设置。为了永久的保存这些选择状态,甚至当activity进程被彻底杀死,你需要用一种数据存储的技术来保存这些设置。
创建一个像下面图片这样的带有单选按钮列表的AlertDialog:
使用和上面那个例子同样的代码,只是把 setItems()方法用 setSingleChoiceItems() 方法替换掉:
setSingleChoiceItems()方法中的第二个参数是一个选择item的整数值,它是指示这个以0位置开始的列表的第几个item被默认的选中。如果传递的值是-1,那么默认没有任何一个item被选中。
----------------------------------------------------------------------------------------------------------------------------------------------------------
ProgressDialog是AlertDialog类的一个扩展,它能够显示一个进度动画,旋转盘形式的ProgressDialog是一个不明确的进度的任务,进度条形式的ProgressDialog是一个明确的进度的任务。这种dialog也可以有button,例如一个取消下载的button。
显示一个ProgressDialog就是简单的调用 ProgressDialog.show()方法。例如:下面的这个ProgressDialog:
不用通过 onCreateDialog(int)回调方法管理,只需要下面的代码就可以简单的实现:
第一个参数是应用程序的context,第二个参数是这个dialog的标题(这里设置为空),第三个参数是一个文本信息,最后一个参数是设置这个dialog是否是不确定性的(这个仅仅和创建一个progress bar有关,这部分内容将在下面的部分讨论)。
默认的ProgressDialog的形式是旋转盘。如果你想创建一个可以显示进度信息的progress bar,你需要再编写一些代码,这部分内容将在下面的部分讨论。
显示一个进度条
用一个带有动画的进度条显示进度:
1)用 ProgressDialog(Context) 构造方法初始化一个 ProgressDialog。
2)用 setProgressStyle(int) 方法设置进度形式为 "STYLE_HORIZONTAL",然后设置其他的一些属性,例如文本信息。
3)当你想要显示这个 ProgressDialog时,在 onCreateDialog(int)回调方法中调用show()方法返回这个 ProgressDialog对象。
4)你可以通过调用 setProgress(int)方法传递一个目前完成的进度值或者incrementProgressBy(int)方法传递一个要增加的值加到目前完成的进度值上来增加进度条上进度的显示。
如下图:
例如,你的设置可能如下:
这些都是简单的设置。创建一个ProgressDialog需要更多的代码去更新它的进度。你可能会发现需要在你的应用中创建第二个线程去完成这些工作,在activity的UI线程下通过一个Handler对象来通知ProgressDialog。如果你不熟悉用一个额外的线程通过Handler对象,你可以参考下面这个利用第二个线程增加ProgressDialog的进度activity的示例。
利用第二个线程的ProgressDialog示例:
这个示例利用第二个线程去跟踪ProgressDialog的进度(实际是就是到100%)。每次进度变化这个线程都会通过一个Handler发送一个信息到这个main activity。然后这个main activity去更新ProgressDialog的进度。
----------------------------------------------------------------------------------------------------------------------------------------------------------
创建一个订制的dialog
如果你想订制一个dialog,你可以用layout 和 widget元素为你的dialog创建自己的布局。你定义完你的布局之后,把你的根视图的对象或者是布局的资源id传递给setContentView(View)方法。
例如,创建一个下面这样的dialog:
1)创建一个xml布局文件,保存为custom_dialog.xml:
这个xml文件定义了一个 ImageView 和一个 TextView 在一个 LinearLayout里面。
2)设置上面的布局作为dialog的内容视图,并且定义 ImageView 和 TextView 元素的内容:
当你实例化一个dialog之后,通过传递布局的资源id用setContentView(int)方法把你订制的布局设置为dialog的内容视图。现在这个dialog有了一个自定义的布局,你可以从布局通过 findViewById(int)方法捕获到视图对象,然后改变它们的内容。
3)就是这些。你现在可以像上面的显示一个dialog中描述的那样显示这个dialog了。
通过基本的Dialog类生成的dialog必须有一个title。如果你没有调用 setTitle()方法,那么title的区域显示为空,但是它仍然可见。如果你根本就不想要一个title,你应该使用AlertDialog类创建你的订制的dialog。然而,因为使用AlertDialog.Builder类可以很简单的创建一个AlertDialog,你不能够访问上面使用的setContentView(int)方法。作为代替,你可以使用 setView(View)方法。
为了得到一个xml布局,可以通过 getLayoutInflater()方法得到一个LayoutInflater对象(或者通过 getSystemService()方法),然后调用 inflate(int, ViewGroup)方法,第一个参数是布局文件的资源id,第二个参数是根视图的id。现在,你可以使用得到的布局来找到视图对象,然后定义 ImageView 和 TextView 元素的内容。然后实例化AlertDialog.Builder类,接着通过setView(View)方法把刚才得到的布局设置成这个dialog的内容视图。
这有一个例子,在一个AlertDialog里面创建一个订制的布局:
更多的信息,可以参考 Dialog 和 AlertDialog.Builder类的参考文档。