java android对话框_对话框  |  Android 开发者  |  Android Developers

对话框是提示用户做出决定或输入更多信息的小窗口。对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模态框事件。

对话框设计

如需了解如何设计对话框(包括语言建议),请阅读对话框设计指南。

6dd3706bed2d16dab5f0261b1aecb067.png

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

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

注意: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();

}

}

efe77b6bd53fdd6f5c02bd44e8308d68.png

图 1. 包含一条消息和两个操作按钮的对话框。

现在,当您创建此类的实例并对该对象调用

下一部分将详细介绍如何使用

根据对话框的复杂度,您可以在 Fragment 生命周期方法。

构建提醒对话框

您可以使用

7240a92407e84bfecec5cc6c5305abde.png

图 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() 方法需要一个按钮标题(由字符串资源提供)和一个

您可以添加三种不同的操作按钮:

肯定

您应该使用此按钮来接受并继续执行操作(“确定”操作)。

否定

您应该使用此按钮来取消操作。

中性

此按钮应用于用户可能不想继续执行操作,但也未必想要取消操作的情况。它出现在肯定按钮和否定按钮之间。例如,实际操作可能是“稍后提醒我”。

对于每种按钮类型,您只能为

f0b1f629c16dee96b5a5b046032bece8.png

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

}

由于列表出现在对话框的内容区域,因此对话框无法同时显示消息和列表,您应通过

如果您选择通过 使用适配器构建布局和加载器指南中对此做了进一步描述。

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

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

ffa991ed4e7da6e1264d7a6b553d29c1.png

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

}

尽管传统列表和带有单选按钮的列表均提供“单选”操作,但若想保留用户的选择,则应使用

创建自定义布局

91e2504d0d77eef63a3939fdb82b832f.png

图 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 的样式,请参阅样式和主题指南。

关闭对话框

当用户轻触使用

系统还会在用户轻触对话框列表中的项时关闭对话框,列表使用单选按钮或复选框的情况除外。否则,您可以通过对

如果需要在对话框消失时执行特定操作,您可以在

您还可取消对话框。此特殊事件表示用户显式离开对话框,且并未完成任务。如果用户按“返回”按钮、轻触屏幕上对话框区域之外的位置,或者您对

如上例所示,您可以通过在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值