显示对话框

显示对话框

尝试 Compose 方式

Jetpack Compose 是 Android 推荐的界面工具包。了解如何在 Compose 中添加组件。

对话框 →

对话框 (dialog) 是一个小窗口,用于提示用户做出决定或输入额外信息。对话框不会填满屏幕,通常用于要求用户在继续操作之前执行某项操作的模式事件。

注意:有关如何设计对话框的信息(包括语言建议),请阅读Material Design Dialogs 准则。

图 1. 基本对话框。

Dialog 类是对话框的基类,但请勿直接实例化 Dialog。请改用以下子类之一

AlertDialog

可显示标题、最多三个按钮、可选项目列表或自定义布局的对话框。

DatePickerDialog 或 TimePickerDialog

具有预定义界面,允许用户选择日期或时间的对话框。

注意:Android 包含另一个名为 ProgressDialog 的对话框类,用于显示带有进度条的对话框。此微件已弃用,因为它在显示进度时阻止用户与应用互动。如果您需要指示加载或不确定进度,请遵循进度和活动中的设计准则,并在布局中使用 ProgressBar,而不是使用 ProgressDialog。

这些类定义了对话框的样式和结构。您还需要一个 DialogFragment 作为对话框的容器。DialogFragment 类提供了创建对话框和管理其外观所需的所有控件,而无需直接调用 Dialog 对象上的方法。

使用 DialogFragment 管理对话框可以使其正确处理生命周期事件,例如用户轻触“返回”按钮或旋转屏幕时。DialogFragment 类还允许您将对话框界面作为可嵌入组件在更大的界面中重复使用,就像传统的 Fragment 一样,例如当您希望对话框界面在大屏和小屏设备上显示不同时。

本文档的以下部分介绍了如何结合使用 DialogFragment 和 AlertDialog 对象。如果您想创建日期或时间选择器,请阅读向您的应用添加选择器。

创建对话框片段

您可以通过扩展 DialogFragment 并在 onCreateDialog() 回调方法中创建 AlertDialog 来实现各种对话框设计,包括自定义布局以及Material Design Dialogs 中描述的设计。

例如,以下是在 DialogFragment 中管理的基本 AlertDialog

Kotlin

class StartGameDialogFragment : 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("Start game")

.setPositiveButton("Start") { dialog, id ->

// START THE GAME!

}

.setNegativeButton("Cancel") { dialog, id ->

// User cancelled the dialog.

}

// Create the AlertDialog object and return it.

builder.create()

} ?: throw IllegalStateException("Activity cannot be null")

}

}

class OldXmlActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_old_xml)

StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG")

}

}

Java

public class StartGameDialogFragment 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_start_game)

.setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int id) {

// START THE GAME!

}

})

.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int id) {

// User cancels the dialog.

}

});

// Create the AlertDialog object and return it.

return builder.create();

}

}

// ...

StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG");

当您创建此类的一个实例并对该对象调用 show() 时,对话框会显示,如下图所示。

图 2. 带有消息和两个操作按钮的对话框。

下一节提供了有关使用 AlertDialog.Builder API 创建对话框的更多详细信息。

根据对话框的复杂程度,您可以在 DialogFragment 中实现多种其他回调方法,包括所有基本的片段生命周期方法。

构建警告对话框

AlertDialog 类允许您构建各种对话框设计,并且通常是您唯一需要的对话框类。如下图所示,警告对话框有三个区域

标题:这是可选的,仅在内容区域被详细消息、列表或自定义布局占据时使用。如果您只需要陈述简单的消息或问题,则不需要标题。

内容区域:此处可以显示消息、列表或其他自定义布局。

操作按钮:对话框中最多可以有三个操作按钮。

AlertDialog.Builder 类提供的 API 允许您创建包含这些类型内容的 AlertDialog,包括自定义布局。

要构建 AlertDialog,请执行以下操作

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)

builder

.setMessage("I am the message")

.setTitle("I am the title")

val dialog: AlertDialog = builder.create()

dialog.show()

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.

AlertDialog dialog = builder.create();

上一个代码片段生成此对话框

图 3. 基本警告对话框的布局。

添加按钮

要添加如图 2 所示的操作按钮,请调用 setPositiveButton() 和 setNegativeButton() 方法

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)

builder

.setMessage("I am the message")

.setTitle("I am the title")

.setPositiveButton("Positive") { dialog, which ->

// Do something.

}

.setNegativeButton("Negative") { dialog, which ->

// Do something else.

}

val dialog: AlertDialog = builder.create()

dialog.show()

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 taps OK button.

}

});

builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int id) {

// User cancels the dialog.

}

});

// Set other dialog properties.

...

// Create the AlertDialog.

AlertDialog dialog = builder.create();

set...Button() 方法需要按钮的标题(由字符串资源提供)和定义用户轻触按钮时执行的操作的 DialogInterface.OnClickListener。

您可以添加三种操作按钮

Positive(肯定):使用此按钮接受并继续操作(即“确定”操作)。

Negative(否定):使用此按钮取消操作。

Neutral(中性):当用户可能不想继续操作,但也不一定想取消时,请使用此按钮。它显示在肯定和否定按钮之间。例如,操作可能是“稍后提醒我”。

您只能向 AlertDialog 添加每种按钮类型的一个按钮。例如,您不能拥有多个“positive”按钮。

上一个代码片段会显示一个警告对话框,如下所示

图 4. 带有标题、消息和两个操作按钮的警告对话框。

添加列表

AlertDialog API 提供三种类型的列表

传统的单选列表。

永久性单选列表(单选按钮)。

永久性多选列表(复选框)。

要创建如图 5 所示的单选列表,请使用 setItems() 方法

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)

builder

.setTitle("I am the title")

.setPositiveButton("Positive") { dialog, which ->

// Do something.

}

.setNegativeButton("Negative") { dialog, which ->

// Do something else.

}

.setItems(arrayOf("Item One", "Item Two", "Item Three")) { dialog, which ->

// Do something on item tapped.

}

val dialog: AlertDialog = builder.create()

dialog.show()

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();

}

此代码片段会生成一个对话框,如下所示

图 5. 带有标题和列表的对话框。

由于列表显示在对话框的内容区域中,因此对话框不能同时显示消息和列表。使用 setTitle() 为对话框设置标题。要指定列表中的项目,请调用 setItems() 并传入一个数组。此外,您还可以使用 setAdapter() 来指定列表。这使您可以使用 ListAdapter 通过动态数据(例如数据库中的数据)支持列表。

如果您使用 ListAdapter 支持列表,请务必使用 Loader,以便内容异步加载。此内容在使用适配器构建布局和加载器中有进一步介绍。

注意:默认情况下,轻触列表项会关闭对话框,除非您使用以下永久性选择列表之一。

添加永久性多选或单选列表

要添加多选项目(复选框)列表或单选项目(单选按钮)列表,请分别使用 setMultiChoiceItems() 或 setSingleChoiceItems() 方法。

例如,您可以按以下方式创建如图 6 所示的多选列表,并将选定的项目保存在 ArrayList 中

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)

builder

.setTitle("I am the title")

.setPositiveButton("Positive") { dialog, which ->

// Do something.

}

.setNegativeButton("Negative") { dialog, which ->

// Do something else.

}

.setMultiChoiceItems(

arrayOf("Item One", "Item Two", "Item Three"), null) { dialog, which, isChecked ->

// Do something.

}

val dialog: AlertDialog = builder.create()

dialog.show()

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 checks the item, add it to the selected

// items.

selectedItems.add(which);

} else if (selectedItems.contains(which)) {

// If the item is already in the array, remove it.

selectedItems.remove(which);

}

}

})

// Set the action buttons

.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int id) {

// User taps OK, so save the selectedItems results

// somewhere or return them to the component that opens the

// dialog.

...

}

})

.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int id) {

...

}

});

return builder.create();

}

图 6. 多选项目列表。

单选警告对话框可按如下方式获得

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)

builder

.setTitle("I am the title")

.setPositiveButton("Positive") { dialog, which ->

// Do something.

}

.setNegativeButton("Negative") { dialog, which ->

// Do something else.

}

.setSingleChoiceItems(

arrayOf("Item One", "Item Two", "Item Three"), 0

) { dialog, which ->

// Do something.

}

val dialog: AlertDialog = builder.create()

dialog.show()

Java

String[] choices = {"Item One", "Item Two", "Item Three"};

AlertDialog.Builder builder = AlertDialog.Builder(context);

builder

.setTitle("I am the title")

.setPositiveButton("Positive", (dialog, which) -> {

})

.setNegativeButton("Negative", (dialog, which) -> {

})

.setSingleChoiceItems(choices, 0, (dialog, which) -> {

});

AlertDialog dialog = builder.create();

dialog.show();

结果如下例所示

图 7. 单选项目列表。

创建自定义布局

如果您想在对话框中使用自定义布局,请创建布局并通过对 AlertDialog.Builder 对象调用 setView() 将其添加到 AlertDialog。

图 8. 自定义对话框布局。

默认情况下,自定义布局会填满对话框窗口,但您仍然可以使用 AlertDialog.Builder 方法添加按钮和标题。

例如,以下是前面自定义对话框布局的布局文件

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"/>

提示:默认情况下,当您将 EditText 元素设置为使用 "textPassword" 输入类型时,字体系列会设置为 monospace。将其字体系列更改为 "sans-serif",以便两个文本字段使用匹配的字体样式。

要在 DialogFragment 中膨胀布局,请使用 getLayoutInflater() 获取 LayoutInflater 并调用 inflate()。第一个参数是布局资源 ID,第二个参数是布局的父视图。然后,您可以调用 setView() 将布局放置在对话框中。示例如下。

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 it's 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 it's 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 作为对话框显示,而不是使用 Dialog API。创建一个 Activity,并在 清单元素中将其主题设置为 Theme.Holo.Dialog

现在 Activity 会显示在对话框窗口中,而不是全屏显示。

将事件传回对话框的宿主

当用户轻触对话框的操作按钮之一或从其列表中选择项目时,您的 DialogFragment 可能会自行执行必要的操作,但通常您希望将事件传递给打开对话框的 activity 或 fragment。为此,请定义一个包含每种点击事件方法 的接口。然后,在接收对话框的操作事件的宿主组件中实现该接口。

例如,以下是一个 DialogFragment,它定义了一个接口,通过该接口将事件传回宿主 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 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 you 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 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 you 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 使用对话框片段的构造函数创建对话框实例,并通过实现 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 taps the dialog's positive button.

}

override fun onDialogNegativeClick(dialog: DialogFragment) {

// User taps 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 taps the dialog's positive button.

...

}

@Override

public void onDialogNegativeClick(DialogFragment dialog) {

// User taps the dialog's negative button.

...

}

}

由于宿主 Activity 实现了 NoticeDialogListener(上例中所示的 onAttach() 回调方法强制要求),对话框片段可以使用接口回调方法向 Activity 传递点击事件

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_start_game)

.setPositiveButton(R.string.start,

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_start_game)

.setPositiveButton(R.string.start, 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();

}

}

显示对话框

当您想显示对话框时,请创建 DialogFragment 的实例,并调用 show(),传入 FragmentManager 和对话框片段的标签名。

您可以从 FragmentActivity 调用 getSupportFragmentManager() 或从 Fragment 调用 getParentFragmentManager() 获取 FragmentManager。示例如下:

Kotlin

fun confirmStartGame() {

val newFragment = StartGameDialogFragment()

newFragment.show(supportFragmentManager, "game")

}

Java

public void confirmStartGame() {

DialogFragment newFragment = new StartGameDialogFragment();

newFragment.show(getSupportFragmentManager(), "game");

}

第二个参数 "game" 是一个唯一的标签名,系统在必要时用于保存和恢复 fragment 状态。您也可以通过调用 findFragmentByTag(),利用该标签获取 fragment 的句柄。

全屏显示对话框或将其作为嵌入式片段显示

您可能希望界面的某个部分在某些情况下显示为对话框,而在其他情况下显示为全屏或嵌入式 fragment。您可能还希望它根据设备的屏幕尺寸显示不同。DialogFragment 类提供了实现此目的的灵活性,因为它可以作为可嵌入的 Fragment 行为。

但是,在这种情况下,您不能使用 AlertDialog.Builder 或其他 Dialog 对象来构建对话框。如果您希望 DialogFragment 可嵌入,请在布局中定义对话框的 UI,然后在 onCreateView() 回调中加载布局。

以下是一个 DialogFragment 示例,它可以使用名为 purchase_items.xml 的布局,以对话框或可嵌入 fragment 的形式出现

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 a 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 the dialog characteristics. For example,

// the dialog includes a title by default, but your custom layout might

// not need it. 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 a 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 the dialog characteristics. For example,

// the dialog includes a title by default, but your custom layout might

// not need it. 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 polished look, 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 polished look, 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 事务的详细信息,请参阅片段。

在此示例中,布尔值 mIsLargeLayout 指定当前设备是否必须使用应用的大布局设计,并因此将此 fragment 显示为对话框而非全屏。设置此类布尔值的最佳方法是声明一个 bool 资源值,并为不同的屏幕尺寸提供备用资源值。例如,以下是 bool 资源的两个版本,适用于不同的屏幕尺寸

res/values/bools.xml

false

res/values-large/bools.xml

true

然后,您可以在 activity 的 onCreate() 方法期间初始化 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 显示为对话框通常适用于为小屏设备设计的应用,并且您希望通过将短期 activity 显示为对话框来改进平板电脑上的体验。

若要仅在大屏设备上将 activity 显示为对话框,请将 Theme.Holo.DialogWhenLarge 主题应用到 清单元素

有关使用主题设置 activity 样式的更多信息,请参阅样式和主题。

关闭对话框

当用户轻触使用 AlertDialog.Builder 创建的操作按钮时,系统会自动关闭对话框。

当用户轻触对话框列表中的项目时,系统也会关闭对话框,除非列表使用单选按钮或复选框。否则,您可以对 DialogFragment 调用 dismiss() 来手动关闭对话框。

如果对话框消失时需要执行某些操作,您可以在 DialogFragment 中实现 onDismiss() 方法。

您还可以取消对话框。这是一个特殊事件,表示用户未完成任务就离开对话框。当用户轻触“返回”按钮或对话框区域外部的屏幕,或者您明确对 Dialog 调用 cancel() 时(例如,作为对话框中“取消”按钮的响应),就会发生此事件。

如上例所示,您可以在 DialogFragment 类中实现 onCancel() 来响应取消事件。

注意:每当触发 onCancel() 回调的事件发生时,系统都会调用 onDismiss()。但是,如果您调用 Dialog.dismiss() 或 DialogFragment.dismiss(),系统会调用 onDismiss(),但不会调用 onCancel()。您通常会在用户轻触对话框中的肯定按钮时调用 dismiss(),以便从视图中移除对话框。

相关推荐