对话框通常是一个显示在当前Activity之前的小窗口。它下面的Activity会失去焦点,并且对话框会接受所有的用户交互。对话框通常用于通知用户中断操作的,并且要执行与应用程序内进度直接相关的短期任务(如进度条或登录提示)。
Dialog类是创建对话框的基类。但你通常不应该直接实例化Dialog类,而应该使用以下之类。
AlertDialog
一个能够有一个、两个、三个或没有按钮的对话框,并且能够包含一组复选框或单选按钮的可选项列表。AlertDialog对话框有构造大多数对话框用户界面的能力,并且是被建议的对话框类型。
ProgressDialog
显示一个进度滚轮或进度条的对话框。因为它是AlertDialog类型对话框的扩展,所以它也支持按钮。
DatePickerDialog
允许用户选择日期的对话框。
TimePickerDialog
允许用户选择时间的对话框。
如果你喜欢定制自己对话框,你能够继承Dialog类或上面介绍的任何子类,并且要定义一个新的布局。
显示对话框
对话框总是作为Activity的一部分来创建和显示的。你通常应该在Activity的onCreateDialog(int)回调方法内创建对话框。在使用这个回调方法时,Android系统会自动的管理每个对话框的状态,并且把它们跟Activity挂在一起,让Activity成为每个对话框的拥有者。这样每个对话框都会从Activity中继承一些属性。例如,当对话框打开时,菜单键依然能够显示给Activity定义的选项菜单,并且音量调节键依然能调整Activity使用的音频流的音量。
注意:如果你在onCreateDialog()方法外部创建了一个对话框,那么它就不会跟Activity捆绑在一起。但是,你能够使用setOwnerActivity(Activity)方法来完成捆绑操作。
在首次请求一个对话框是,Android会调用源自Activity中的onCreateDialog(int)方法,这是初始化对话框的地方。这个回调方法被传入一个与你传递给showDialog(int)方法相同的ID。创建了这个对话框后,在这个回调方法的最后返回对话框对象。
在对话框显示之前,Android系统也会选择性的调用onPrepareDialog(int, Dialog)回调方法。如果你想要每次打开对话框时都要改变它的一些属性,那么就要定义这个方法。这个方法在每次打开对话框时被调用,而onCreateDialog(int)方法仅会在首次打开对话框时被调用。如果你没有定义onPrepareDialog()方法,那么对话框会保留它前次被打开的状态。这个方法也要传递一个对话框的ID,跟在onCreateDialog()方法中创建对话框对象的ID一样。
定义onCreateDialog(int)和onPrepareDialog(int, Dialog)回调方法的最好方式是使用一个switch语句来检查传递给这个方法的id参数,每个case语句应该用来检查唯一的对话框ID,对于匹配的ID就创建和定义对应的对话框。例如,假设一个使用两个不同对话框的游戏,一个指示游戏已经被挂起了,另一个指示游戏结束了。首先要给每个对话框定义一个整数ID:
static final int DIALOG_PAUSED_ID = 0;
static final int DIALOG_GAMEOVER_ID = 1;
然后用户switch语句定义onCreateDialog(int)回调方法。
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;
}
注意:这个例子中,每个case语句中没有代码,因为定义对话框的过程超出了本节讨论的范围。在下面创建AlertDialog对话框一节中,会提供适合这个例子的代码。
当要显示一个对话框时,要调用带有这个对话框ID的showDialog(int)方法:
showDialog(DIALOG_PAUSED_ID);
废弃话框
当你准备关闭对话框时,你能够在对话框对象上调用dismiss()方法来废弃它,如果需要,也能够从Activity中调用dismissDialog(int)方法,它与对话框上的dismiss()方法等效。
如果你使用onCreateDialog(int)方法来管理对话框的状态,那么对话框每次被废弃后,这个对话框对象的状态会依然被它的Activity保留着。如果你决定不再需要这个对象,或者清除它的状态是至关重要的,那么应该调用removeDialog(int)方法。这样就会删除应用内部对这个对话框对象的任何引用,并且如果对话框正显示着,removeDialog(int)方法也会废弃它。
使用废弃监听器
如果你要让应用程序在对话框被废弃时执行一些处理,那么就应该给这个对话框绑定一个on-dismiss监听器。
首先要定义DialogInterface.OnDismissListener接口。这个接口只有一个onDismiss(DialogInterface)方法,它在对话框被废弃时被调用。然后把OnDismissListener的接口实现传递给setOnDismissListener()方法。
但是,要注意,对话框也能被取消。这种特定的情况是指对话框被用户明确的取消。如果用户按了回退按钮来关闭对话框或对话框明确的调用了cancel()方法(如用户点击了对话框中的取消按钮)就会发生这种情况。当对话框被取消时,onDismissListener回调依然会收到通知,但是如果你希望得到对话框明确的取消(不是废弃)的通知,那么你应该用setOnCancelListener()方法注册一个DialogInterface.OnCancelListener监听器。
创建AlertDialog型对话框
AlertDialog型对话框是Dialog类的扩展,它有构建大多数对话框用户界面的能力,并且是被建议使用的对话框类型。对于具有下列特征的对话框,你都应该使用这种类型的对话框。
1.标题;
2.文本消息;
3.有一个、两个或三个按钮;
4.一个可选项目的列表(一组复选框或单选按钮)。
使用AlertDialog.Builder子类来创建一个AlerDialog型的对话框。用AlertDialog.Builder(Context)方法获得一个构造器,然后使用这个构造器的公共方法来定义所有的对话框属性。用这个构造器设定完对话框属性之后,就可以用create()方法来获取AlertDialog对话框对象。
以下说明如何使用AlertDialog.Builder类来定义AlertDialog对话框的各种属性。如果你在onCreateDialog()方法中使用下面示例中任何代码,那么就能够返回让对话框显示的对话框对象。
添加按钮
使用set…Button()方法创建一个带有两并排按钮的对话框,如图1所示:
创建代码如下:
AlertDialog.Builder builder =newAlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes",newDialogInterface.OnClickListener(){
publicvoid onClick(DialogInterface dialog,int id){
MyActivity.this.finish();
}
})
.setNegativeButton("No",newDialogInterface.OnClickListener(){
publicvoid onClick(DialogInterface dialog,int id){
dialog.cancel();
}
});
AlertDialog alert = builder.create();
首先用setMessage(CharSequence)方法给对话框添加一个消息。然后开始设置对话框属性,并且用setCancelable(Boolean)方法设置对话框不可取消(用户不能够永回退按钮关闭这个对话框)。使用set…Button方法来添加每个按钮,如setPositiveButton()方法,它接受一个按钮的名称和定义用户选择按钮时要执行的操作的DialogInterface.OnClickListener()回调方法。
注意:每种类型的按钮,你只能给AlerDialog对话框添加一个。也就是说你不能有多个”positive”按钮。这样就限制了三种按钮可能的数量:positive、neutral、negative。这些名字不代表按钮的实际功能,但是它们能够帮助你记忆每个按钮做要做的操作。
添加一个列表
要创建一个如图2所示的带有可选项列表的AlertDialog型对话框,就要使用setItems()方法:
图2.
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();
首先,用setTitle(charSequence)方法给对话框添加一个标题,然后,用setItems()方法让添加一个可选列表,这个方法需要两个参数:一个是要显示的列表项数组,另一个是定义用户选择项目时所以执行的操作的DialogInterface.OnClickListener监听器。
添加复选框和单选按钮
分别使用setMultiChoiceItems()和setSingleChoiceItems()方法,在对话框内部创建一个多选(复选框)或单选(单选按钮)项目的列表。如果你在onCreateDialog()回调方法中创建了其中一种可选列表,Android系统会为你管理列表的状态。对话框记住之前被选择的项目的时间会跟它所捆绑的Activity的生存周期一样长,当用户推出这个Activity时,对话框对应的选择也就丢失了。
注意:要在用户离开或挂起Activity时保存选择的项目,就必须在整个Activity生存周期中恰当的保存和恢复这些设置。要持久的保存被选择的项目,即使是在Activity处理被完成销毁时,就需要用一种数据存储技术来保存这些设置。
要创建一个如下图3所示的单选项目列表的AlertDialog型对话框,会使用与前面的示例代码相同的代码,但是要用setSingleChoiceItems()方法替代setItems()方法。
图3
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();
setSingleChoiceItems()方法的第二个参数是可选项目列表中项目的索引值,默认可选项目的位置是0,如果使用”-1”,那么默认情况下,就不应该有列表项被选择。
创建进度对话框
ProgressDialog是AlertDialog类的一个扩展,它能够用滚轮动画的形式显示一个未明确定义进度的任务,或者用一个进度条来显示明确定义了进度的任务。这中对话框也能够提供按钮,如取消按钮。
能够简单的调用ProgressDialog.show()方法来打开一个进度对话框。通过onCreateDialog(int)回调方法可以很容易的把图4所示的没有接受管理的对话框捆绑到指定的Activity上。
图4
sDialog dialog =ProgressDialog.show(MyActivity.this,"",
"Loading. Please wait...",true);
这个方法的第一个参数是应用程序的Context对象,第二个参数是对话框的标题(设置为空),第三个参数是消息,最后一个参数指定进度是否是不确定的。
进度对话框的默认样式是一个旋转的轮子。如果你想要创建一个显示加载进度的进度条对话框,请看下节的讨论。
显示进度条
显示一个如图5所示的带有动画的进度条的步骤如下:
1.用类构造器(ProgressDialog(Context))实例化一个ProgressDialog型对话框;
2.用setProgressStyle(int)方法设置进度条的样式:STYLE_HORIZONTAL,并且设置其他属性,如消息等。
3.准备显示对话框时,调用show()方法,或者从onCreateDialog(int)回调方法中返回ProgressDialog对象;
4.你既可以通过调用setProgress(int)方法也可以调用incrementProgressBy(int)方法来设置显示进度的增量。不同的是setProgress(int)方法用到目前为止完成总的百分比值来设置进度,而incrementProgressBy(int)方法是用到目前为止总的进度的增量值来设置进度条的显示。
如:可能步骤如下:
ProgressDialog progressDialog;
progressDialog =newProgressDialog(mContext);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
创建一个定制的对话框
如果你要定制设计一个对话框,你能够给对话框窗口创建自己的布局,这个布局带有布局和可视构件元素。定义完布局以后,把根View对象或布局资源ID传递给setContentView(view)方法。
如,创建一个如图6所示的对话框的步骤如下:
图6
1.创建一个保存在custom_dialog.xml文件中的XML布局
<LinearLayoutxmlns:android="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"
>
<ImageViewandroid:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
<TextViewandroid:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFF"
/>
</LinearLayout>
这个XML在LinearLayout元素内部定义了一个ImageView对象和TextView对象。
2.把上面的这个布局设置为对话框的内容视窗,并且给ImageView和TextView元素定义显示内容:
Context mContext = getApplicationContext();
Dialog dialog =newDialog(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);
实例化对话框之后,用setContentView(int)方法,把你定制的布局设置给对话框的内容视窗。现在对话框已经有了一个被定义的布局,你能够用findViewById(int)方法从布局中获取View对象,并可以修改它们的内容。
3.用上面介绍的显示对话框的方法显示对话框。
用基本对话框构造的对话框一定会有一个标题栏。如果你没有调用setTitle()方法,那么标题所使用的空间就会使空的,但依然可见。如果你不想要标题,那么就应该使用AlertDialog类创建定制的对话框。但是,因为AlertDialog型对话框用AlertDialog.Builder类最容易创建,所以不会使用上面的setContentView(int)方法。相反,你必须使用setView(View)方法。这个方法接受一个View对象,以便把布局填充到指定的View对象中。
用getLayoutInflater()方法(或getSystemService()方法)获取LayoutInflater对象,然后调用这个对象的inflate(int, ViewGroup)方法来填充XML布局。第一个参数是布局的资源ID,第二个参数是根View对象的ID。这时,你能够使用被填充的布局来查找布局中的View对象,并且给ImageView和TextView元素定义内容,然后实例化这个AlertDialog.Builder对象,并用setView(View)方法把填充好的布局设置给对话框。
以下示例,在AlertDialog型对话框中创建一个定制的布局:
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 =newAlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();
给定制的布局使用AlertDialog型对话框,你会利用AlertDialog型对话框内置特征,如按钮管理、可选列表、标题、图标等。