对话框是提示用户做出决定或输入更多信息的小窗口。对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模态框事件。
对话框设计
如需了解如何设计对话框(包括语言建议),请阅读对话框设计指南。

此对话框可显示标题、最多三个按钮、可选择项列表或自定义布局。
此对话框带有允许用户选择日期或时间的预定义界面。
注意:Android 包含另一种名为 进度和 Activity 的设计准则,并在布局中使用
这些类可为您的对话框定义样式和结构,但您应使用
使用 此外,
本指南接下来将介绍如何将 选择器指南。
注意:由于 支持库附带的 android.support.v4.app.DialogFragment 类,而不是 android.app.DialogFragment。
创建对话框 Fragment
通过扩展 对话框设计指南中描述的布局。
Kotlin
class FireMissilesDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire,
DialogInterface.OnClickListener { dialog, id ->
// FIRE ZE MISSILES!
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
// Create the AlertDialog object and return it
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}Java
public class FireMissilesDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}

图 1. 包含一条消息和两个操作按钮的对话框。
现在,当您创建此类的实例并对该对象调用
下一部分将详细介绍如何使用
根据对话框的复杂度,您可以在 Fragment 生命周期方法。
构建提醒对话框
您可以使用

图 2. 对话框的布局。
标题
这是可选项,只应在详细消息、列表或自定义布局占据内容区域时使用。如果需要陈述的是一条简单消息或问题(如图 1 中的对话框),则不需要标题。
内容区域
它可以显示消息、列表或其他自定义布局。
操作按钮
对话框中的操作按钮不应超过三个。
您可以使用
如需构建
Kotlin
// 1. Instantiate an AlertDialog.Builder with its constructor
val builder: AlertDialog.Builder? = activity?.let {
AlertDialog.Builder(it)
}
// 2. Chain together various setter methods to set the dialog characteristics
builder?.setMessage(R.string.dialog_message)
.setTitle(R.string.dialog_title)
// 3. Get the AlertDialog from create()
val dialog: AlertDialog? = builder?.create()Java
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(R.string.dialog_message)
.setTitle(R.string.dialog_title);
// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();
以下主题介绍如何使用
添加按钮
Kotlin
val alertDialog: AlertDialog? = activity?.let {
val builder = AlertDialog.Builder(it)
builder.apply {
setPositiveButton(R.string.ok,
DialogInterface.OnClickListener { dialog, id ->
// User clicked OK button
})
setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
}
// Set other dialog properties
...
// Create the AlertDialog
builder.create()
}Java
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Set other dialog properties
...
// Create the AlertDialog
AlertDialog dialog = builder.create();
set...Button() 方法需要一个按钮标题(由字符串资源提供)和一个
您可以添加三种不同的操作按钮:
肯定
您应该使用此按钮来接受并继续执行操作(“确定”操作)。
否定
您应该使用此按钮来取消操作。
中性
此按钮应用于用户可能不想继续执行操作,但也未必想要取消操作的情况。它出现在肯定按钮和否定按钮之间。例如,实际操作可能是“稍后提醒我”。
对于每种按钮类型,您只能为

图 3. 包含标题和列表的对话框。
添加列表
可通过
传统的单选列表
永久性单选列表(单选按钮)
永久性多选列表(复选框)
如需创建如图 3 所示的单选列表,请使用
Kotlin
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = AlertDialog.Builder(it)
builder.setTitle(R.string.pick_color)
.setItems(R.array.colors_array,
DialogInterface.OnClickListener { dialog, which ->
// The 'which' argument contains the index position
// of the selected item
})
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}Java
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color)
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
}
});
return builder.create();
}
由于列表出现在对话框的内容区域,因此对话框无法同时显示消息和列表,您应通过
如果您选择通过 使用适配器构建布局和加载器指南中对此做了进一步描述。
注意:默认情况下,轻触列表项会关闭对话框,除非您使用的是以下某一种永久性选择列表。
添加永久性多选列表或永久性单选列表

图 4. 多选项列表。
例如,以下示例展示了如何创建如图 4 所示的多选列表,该多选列表将选定项保存在
Kotlin
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val selectedItems = ArrayList() // Where we track the selected items
val builder = AlertDialog.Builder(it)
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(R.array.toppings, null,
DialogInterface.OnMultiChoiceClickListener { dialog, which, isChecked ->
if (isChecked) {
// If the user checked the item, add it to the selected items
selectedItems.add(which)
} else if (selectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
selectedItems.remove(Integer.valueOf(which))
}
})
// Set the action buttons
.setPositiveButton(R.string.ok,
DialogInterface.OnClickListener { dialog, id ->
// User clicked OK, so save the selectedItems results somewhere
// or return them to the component that opened the dialog
...
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
...
})
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}Java
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
selectedItems = new ArrayList(); // Where we track the selected items
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
selectedItems.add(which);
} else if (selectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
selectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// User clicked OK, so save the selectedItems results somewhere
// or return them to the component that opened the dialog
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
...
}
});
return builder.create();
}
尽管传统列表和带有单选按钮的列表均提供“单选”操作,但若想保留用户的选择,则应使用
创建自定义布局

图 5. 自定义对话框布局。
如果您想在对话框中使用自定义布局,请创建一个布局,然后通过对
默认情况下,自定义布局会填充对话框窗口,但您仍可使用
例如,以下是图 5 中对话框的布局文件:
res/layout/dialog_signin.xml
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:src="@drawable/header_logo"
android:layout_width="match_parent"
android:layout_height="64dp"
android:scaleType="center"
android:background="#FFFFBB33"
android:contentDescription="@string/app_name" />
android:id="@+id/username"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="@string/username" />
android:id="@+id/password"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="16dp"
android:fontFamily="sans-serif"
android:hint="@string/password"/>
提示:默认情况下,当您将 "textPassword" 输入类型时,字体系列会设置为等宽。因此,您应将其字体系列更改为 "sans-serif",以便两个文本字段均使用匹配的字体样式。
如需膨胀
Kotlin
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = AlertDialog.Builder(it)
// Get the layout inflater
val inflater = requireActivity().layoutInflater;
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton(R.string.signin,
DialogInterface.OnClickListener { dialog, id ->
// sign in the user ...
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
getDialog().cancel()
})
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}Java
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = requireActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
提示:如果您要自定义对话框,可以改用对话框的形式显示 清单元素中将其主题背景设置为
就是如此简单。Activity 现在会显示在一个对话框窗口中,而非全屏显示。
将事件传递回对话框的宿主
当用户轻触对话框的某个操作按钮或从列表中选择某一项时,您的
例如,以下
Kotlin
class NoticeDialogFragment : DialogFragment() {
// Use this instance of the interface to deliver action events
internal lateinit var listener: NoticeDialogListener
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
interface NoticeDialogListener {
fun onDialogPositiveClick(dialog: DialogFragment)
fun onDialogNegativeClick(dialog: DialogFragment)
}
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
override fun onAttach(context: Context) {
super.onAttach(context)
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
listener = context as NoticeDialogListener
} catch (e: ClassCastException) {
// The activity doesn't implement the interface, throw exception
throw ClassCastException((context.toString() +
" must implement NoticeDialogListener"))
}
}
}Java
public class NoticeDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
NoticeDialogListener listener;
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
@Override
public void onAttach(Context context) {
super.onAttach(context);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
listener = (NoticeDialogListener) context;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
...
}
对话框的宿主 Activity 会使用对话框 Fragment 的构造函数创建对话框实例,并通过 NoticeDialogListener 接口的实现接收对话框的事件:
Kotlin
class MainActivity : FragmentActivity(),
NoticeDialogFragment.NoticeDialogListener {
fun showNoticeDialog() {
// Create an instance of the dialog fragment and show it
val dialog = NoticeDialogFragment()
dialog.show(supportFragmentManager, "NoticeDialogFragment")
}
// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the NoticeDialogFragment.NoticeDialogListener interface
override fun onDialogPositiveClick(dialog: DialogFragment) {
// User touched the dialog's positive button
}
override fun onDialogNegativeClick(dialog: DialogFragment) {
// User touched the dialog's negative button
}
}Java
public class MainActivity extends FragmentActivity
implements NoticeDialogFragment.NoticeDialogListener{
...
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
DialogFragment dialog = new NoticeDialogFragment();
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
}
// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the NoticeDialogFragment.NoticeDialogListener interface
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User touched the dialog's positive button
...
}
@Override
public void onDialogNegativeClick(DialogFragment dialog) {
// User touched the dialog's negative button
...
}
}
由于宿主 Activity 会实现 NoticeDialogListener(由以上显示的
Kotlin
override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
return activity?.let {
// Build the dialog and set up the button click handlers
val builder = AlertDialog.Builder(it)
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire,
DialogInterface.OnClickListener { dialog, id ->
// Send the positive button event back to the host activity
listener.onDialogPositiveClick(this)
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
// Send the negative button event back to the host activity
listener.onDialogNegativeClick(this)
})
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}Java
public class NoticeDialogFragment extends DialogFragment {
...
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Build the dialog and set up the button click handlers
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the positive button event back to the host activity
listener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
listener.onDialogNegativeClick(NoticeDialogFragment.this);
}
});
return builder.create();
}
}
显示对话框
如果您想显示对话框,请创建一个
Kotlin
fun confirmFireMissiles() {
val newFragment = FireMissilesDialogFragment()
newFragment.show(supportFragmentManager, "missiles")
}Java
public void confirmFireMissiles() {
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
}
第二个参数 "missiles" 是系统用于保存 Fragment 状态并在必要时进行恢复的唯一标记名称。该标记还允许您通过调用
全屏显示对话框或将其显示为嵌入式 Fragment
您可能采用以下界面设计:想让一部分界面在某些情况下显示为对话框,但在其他情况下全屏显示或显示为嵌入式 Fragment(可能取决于设备使用大屏幕还是小屏幕)。
但在此情况下,您不能使用
以下示例 purchase_items.xml 的布局):
Kotlin
class CustomDialogFragment : DialogFragment() {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.purchase_items, container, false)
}
/** The system calls this only when creating the layout in a dialog. */
override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
val dialog = super.onCreateDialog(savedInstanceState)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
return dialog
}
}Java
public class CustomDialogFragment extends DialogFragment {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.purchase_items, container, false);
}
/** The system calls this only when creating the layout in a dialog. */
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
}
以下代码可根据屏幕尺寸确定将 Fragment 显示为对话框或全屏界面:
Kotlin
fun showDialog() {
val fragmentManager = supportFragmentManager
val newFragment = CustomDialogFragment()
if (isLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog")
} else {
// The device is smaller, so show the fragment fullscreen
val transaction = fragmentManager.beginTransaction()
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction
.add(android.R.id.content, newFragment)
.addToBackStack(null)
.commit()
}
}Java
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment();
if (isLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog");
} else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
}
如需详细了解如何执行 Fragment 事务,请参阅 Fragment 指南。
在本示例中,mIsLargeLayout 布尔值指定当前设备是否应使用应用的大布局设计(进而将此 Fragment 显示为对话框,而非全屏显示)。设置这种布尔值的最佳方式是声明一个布尔资源值,其中包含适用于不同屏幕尺寸的备用资源值。例如,以下两个版本的布尔资源适用于不同屏幕尺寸:
res/values/bools.xml
false
res/values-large/bools.xml
true
然后,您可以在 Activity 的 mIsLargeLayout 值:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
isLargeLayout = resources.getBoolean(R.bool.large_layout)
}Java
boolean isLargeLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
isLargeLayout = getResources().getBoolean(R.bool.large_layout);
}
在大屏幕上将 Activity 显示为对话框
相对于在小屏幕上将对话框显示为全屏界面,您可以在大屏幕上将
如需仅在大屏幕上将 Activity 显示为对话框,请将 清单元素:
如需详细了解如何通过主题设置 Activity 的样式,请参阅样式和主题指南。
关闭对话框
当用户轻触使用
系统还会在用户轻触对话框列表中的项时关闭对话框,列表使用单选按钮或复选框的情况除外。否则,您可以通过对
如果需要在对话框消失时执行特定操作,您可以在
您还可取消对话框。此特殊事件表示用户显式离开对话框,且并未完成任务。如果用户按“返回”按钮、轻触屏幕上对话框区域之外的位置,或者您对
如上例所示,您可以通过在
1228

被折叠的 条评论
为什么被折叠?



