1.What?
我们在开发时常常会碰到这样一些需求:点击某个按钮时弹出一个对话框和用户交互,或者是在某个时刻弹出一个在所有UI顶层之上的悬浮框。怎么实现这种效果呢?
Android为我们提供了PopupWindow和Dialog,正如名字所示,它们就是一类在顶层出现的视图空间。
来看看官方对这两个类的说明。
PopupWindow
This class represents a popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity.
PopupWindow代表一个可以用于显示任何view的弹出窗口。它是一个出现在当前activity顶层的悬浮的容器。
Dialog
对话框是提示用户作出决定或输入额外信息的小窗口。 对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模式事件。
那么这两者有什么区别呢?
注意Dialog的最后一句话:通常用于需要用户采取行动才能继续执行的模式事件。Dialog是阻塞UI线程的,也就是当弹出一个Dialog后,用户必须先处理了Dialog才能继续做其它的事情,而PopupWindow仅仅是一个view的容器,它不会对当前线程造成影响,它是非阻塞的。
另一个重要的区别是:Dialog有固定的位置,它总在屏幕的中央,而PopupWindow没有这个限制,它可以出现在任何地方。
2.How?
下面让我们来看看如何使用PopupWindow和Dialog。
PopupWindow:
使用PopupWindow主要分为两个步骤:
(1)初始化PopupWindow对象,设置contentView、长、宽、是否可以获取焦点等等参数。
(2)显示PopupWindow。
之所以要分为两个阶段,是因为显示是比较重要的问题,前面我们说了PopupWindow与Dialog的不同,正因为PopupWindow可以显示在任意位置,所以如何显示它是需要考虑的,不同于使用Dialog,我们只需要调用dialog.show()
就能解决问题,因为dialog的位置固定,这就是灵活性和复杂性的问题,一个东西越灵活,那么使用起来它就一定越复杂。
首先来看初始化PopupWindow。
创建一个PopupWindow对象,可以在构造函数里传一些初始参数,也可以在创建以后以后手动set。
下面是常用的一些初始化操作:
1 | final PopupWindow window = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT,true); |
当设置好了window以后就可以来显示它了。
显示PopupWindow的方法有两个:
(1)showAsDropDown
使用这种显示方式,window将会显示在指定的view的左下方,可以自己传入x、y方向的偏移量。
(2)showAtLocation
使用这种显示方式,window将会显示在指定的view的内部,并且以该view的左上角为原点。
Demo就不贴了,几行代码比较简单。
需要注意的是不能直接在Activity的onCreate
方法里直接显示PopupWindow,这样会直接报错!这也很好理解,如果你要在开始就显示一个PopupWindow,那么为什么不直接在原来的View里添加呢?
接下来是Dialog。
使用Dialog相比PopupWindow要简单很多。
复杂的是Dialog的继承关系,Google官方的文档上明确的说了不推荐我们直接使用Dialog,而是应该使用它的子类。
下面来看官方说明:
Dialog
类是对话框的基类,但您应该避免直接实例化Dialog
,而是使用下列子类之一:
AlertDialog
此对话框可显示标题、最多三个按钮、可选择项列表或自定义布局。
DatePickerDialog
或TimePickerDialog
此对话框带有允许用户选择日期或时间的预定义 UI。这些类定义您的对话框的样式和结构,但您应该将
DialogFragment
用作对话框的容器。DialogFragment
类提供您创建对话框和管理其外观所需的所有控件,而不是调用Dialog
对象上的方法。使用
DialogFragment
管理对话框可确保它能正确处理生命周期事件,如用户按“返回”按钮或旋转屏幕时。 此外,DialogFragment
类还允许您将对话框的 UI 作为嵌入式组件在较大 UI 中重复使用,就像传统Fragment
一样(例如,当您想让对话框 UI 在大屏幕和小屏幕上具有不同外观时)。
本指南的后文将描述如何将
DialogFragment
与AlertDialog
对象结合使用。 如果您想创建一个日期或时间选取器,应改为阅读选取器指南。注:由于DialogFragment
类最初是通过 Android 3.0(API 级别 11)添加的,因此本文描述的是如何使用支持库附带的DialogFragment
类。 通过将该库添加到您的应用,您可以在运行 Android 1.6 或更高版本的设备上使用DialogFragment
以及各种其他 API。如果您的应用支持的最低版本是 API 级别 11 或更高版本,则可使用DialogFragment
的框架版本,但请注意,本文中的链接适用于支持库 API。 使用支持库时,请确保您导入的是android.support.v4.app.DialogFragment
类,而不是android.app.DialogFragment
。
这个图是我直接从Android Studio中查看类继承关系得到的。官方文档里只提到了其中的几个。
每个类具体的说明这里就不说了,需要时再查。
官方文档里说的DialogFragment其实就是一个内嵌了Dialog的Fragment,它不在这个继承树里,使用这个Fragment的好处时结合生命周期对Dialog进行一些处理。
Dialog的使用非常之简单,下面是一个基本的用法:
1 | /** |
这是一个自定义的简单Dialog,接下来在Activity里使用它。
1 | MyDialog myDialog = new MyDialog(); |
就是这么简单。一个show就可以解决所有事情。
本篇到此为止,更多深入的知识在生产环境上再学习。