Android PopupWindow 和 Dialog Activity的使用

PopupWindow(悬浮框)

Android 中的 PopupWindow 类似 iOS中的UIPopoverPresentationController弹窗,可以显示在某个view的附近,相对于AlertDialog, AlertDialog在位置显示上是固定的(默认是居中,当然也可以通过 dialog.window?.attributes中的x,y改变位置),而PopupWindow则相对比较随意,可以用来显示任意视图(View),而且会浮动在当前活动(activity)的顶部,能够在主屏幕上的任意位置显示。

XML 属性
android:overlapAnchor 弹出窗口是否应与其锚视图重叠。是一个布尔值,例如“ true”或“ false”。
android:popupAnimationStyle 用于弹出窗口的动画样式。可能是对另一个资源的引用,形式为“ ”或形式为“ ”的主题属性。``
android:popupBackground 用于弹出窗口的背景。
android:popupElevation 用于弹出窗口的窗口高度。
android:popupEnterTransition 用于将视图移动到弹出窗口中的过渡。
android:popupExitTransition 用于将视图移出弹出窗口的过渡。
公共构造函数
PopupWindow(context: Context!)创建一个新的空的、不可聚焦的、维度为 (0,0) 的弹出窗口。
PopupWindow(context: Context!, attrs: AttributeSet!)创建一个新的空的、不可聚焦的、维度为 (0,0) 的弹出窗口。
PopupWindow(context: Context!, attrs: AttributeSet!, defStyleAttr: Int)创建一个新的空的、不可聚焦的、维度为 (0,0) 的弹出窗口。
PopupWindow(context: Context!, attrs: AttributeSet!, defStyleAttr: Int, defStyleRes: Int)创建一个新的、空的、不可聚焦的尺寸为 (0,0) 的弹出窗口。
PopupWindow()创建一个新的空的、不可聚焦的、维度为 (0,0) 的弹出窗口。
PopupWindow(contentView: View!)创建一个新的不可聚焦的弹出窗口,它可以显示 contentView。
PopupWindow(width: Int, height: Int)创建一个新的空的、不可聚焦的弹出窗口。
PopupWindow(contentView: View!, width: Int, height: Int)创建一个新的不可聚焦的弹出窗口,它可以显示 contentView。
PopupWindow(contentView: View!, width: Int, height: Int, focusable: Boolean)创建一个可以显示 contentView 的新弹出窗口。
常量
static Int INPUT_METHOD_FROM_FOCUSABLE对输入法的要求应基于弹出窗口的可聚焦性。也就是说,如果它是可聚焦的,而不是它需要使用输入法,否则它不会。
static Int INPUT_METHOD_NEEDED此弹出窗口始终需要与输入法一起使用,无论它是否可聚焦。这意味着它将始终显示,以便用户在显示时也可以操作输入法。
static Int **INPUT_METHOD_NOT_NEEDED **此弹出窗口永远不需要使用输入法,无论它是否可聚焦。这意味着它将始终显示为根据需要在屏幕上使用尽可能多的空间,无论这是否涵盖输入法。
方法返回值 方法名
open Unit **dismiss() **处理弹出窗口。该方法只有在showAsDropDown(android.view.View)执行后才能调用。否则,调用此方法将无效。
open Int getAnimationStyle() 返回弹出框出现和消失的动画样式
open Drawable! getBackground() 返回用作弹出窗口背景的drawable
open View! getContentView()返回用作弹出窗口内容的视图。
open Float getElevation() 获取Elevation
open Transition? getEnterTransition()返回显示弹出窗口时要使用的输入转换。
open Rect? getEpicenterBounds()返回用作进入和退出转换中心的边界。过渡使用 Rect(称为震中)来确定行进方向。对于弹出窗口,锚视图边界用作默认震中。
open Transition? getExitTransition()返回弹出窗口关闭时要使用的退出转换。
open Int getHeight()返回弹出窗口请求的高度。可能是布局常量,例如LayoutParams#WRAP_CONTENTLayoutParams#MATCH_PARENT。弹出窗口的实际大小可能取决于其他因素,例如剪辑和窗口布局。
open Int **getInputMethodMode() **返回 InputMethodMode。
open Int getMaxAvailableHeight(anchor: View)返回可用于完全显示弹出窗口的最大高度。建议将此高度设为弹出窗口高度的最大值,否则可能会剪切弹出窗口。
open Int getMaxAvailableHeight(anchor: View, yOffset: Int)返回可用于完全显示弹出窗口的最大高度。建议将此高度设为弹出窗口高度的最大值,否则可能会剪切弹出窗口。
open Int getMaxAvailableHeight(anchor: View, yOffset: Int, ignoreBottomDecorations: Boolean)返回可用于完全显示弹出窗口的最大高度,可选择忽略任何底部装饰,例如输入法。建议将此高度设为弹出窗口高度的最大值,否则可能会剪切弹出窗口。ignoreBottomDecorations如果为真,返回的高度将一直到显示的底部,忽略任何底部装饰
open Boolean getOverlapAnchor()返回弹出窗口在显示为下拉菜单时是否应与其锚视图重叠。
open Int getSoftInputMode()获取软输入模式 返回值
open Int getWidth()返回弹出窗口的请求宽度。可能是布局常量,例如LayoutParams#WRAP_CONTENTLayoutParams#MATCH_PARENT。弹出窗口的实际大小可能取决于其他因素,例如剪辑和窗口布局。
open Int getWindowLayoutType()返回此窗口的布局类型。
open Boolean isAboveAnchor()指示弹出窗口是显示在上方(弹出窗口底部的 y 坐标小于锚点的 y 坐标)还是下方(弹出窗口的 y 坐标大于锚点底部的 y 坐标)。此方法返回的值只有在showAsDropDown(android.view.View)showAsDropDown(android.view.View,int,int)被调用后才有意义。
open Boolean isAttachedInDecor()指示弹出窗口是否将附加在其父窗口的装饰框架中。
open Boolean isClippedToScreen()指示此弹出窗口是否将被剪切到屏幕而不是包含窗口
open Boolean isClippingEnabled()指示是否启用弹出窗口的剪辑。
open Boolean isFocusable()指示弹出窗口是否可以抓取焦点。
open Boolean isLaidOutInScreen()指示是否将弹出窗口强制使用屏幕绝对坐标进行定位。
open Boolean isOutsideTouchable()指示是否将弹出窗口通知其窗口外的触摸事件。
open Boolean isShowing()指示此弹出窗口是否显示在屏幕上。
open Boolean isSplitTouchEnabled()Indicates whether the popup window supports splitting touches.
open Boolean isTouchModal()指示是否将外部触摸发送到此窗口或它后面的其他窗口
open Boolean isTouchable()指示弹出窗口是否接收触摸事件。
open Unit setAnimationStyle(animationStyle: Int)更改此弹出窗口的动画样式资源。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setAttachedInDecor(enabled: Boolean)这会将弹出窗口附加到父窗口的装饰框架,以避免与导航栏等屏幕装饰重叠。覆盖 flag 的默认行为WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR。默认情况下,该标志在 SDK 版本Build.VERSION_CODES#LOLLIPOP_MR1或更高版本上设置并在较小的 SDK 版本上清除。
open Unit setBackgroundDrawable(background: Drawable!)指定此弹出窗口的背景可绘制。背景可以设置为null
open Unit setClippingEnabled(enabled: Boolean)允许弹出窗口超出屏幕边界。默认情况下,窗口被裁剪到屏幕边界。将此设置为 false 将允许准确定位窗口。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setContentView(contentView: View!)更改弹出窗口的内容。内容由 的实例表示android.view.View。如果在弹出窗口显示时调用此方法,则此方法无效。
open Unit setElevation(elevation: Float) 指定此弹出窗口的elevation。
open Unit setEnterTransition(enterTransition: Transition?)设置显示弹出窗口时要使用的输入转换。
open Unit setEpicenterBounds(bounds: Rect?)设置用作进入和退出转换的中心的边界。过渡使用 Rect(称为震中)来确定行进方向。对于弹出窗口,锚视图边界用作默认震中。
open Unit setExitTransition(exitTransition: Transition?)设置弹出窗口关闭时要使用的退出转换。
open Unit setFocusable(focusable: Boolean)更改弹出窗口的可聚焦性。当可聚焦时,如果弹出窗口包含一个 focusable ,则窗口将从当前聚焦的小部件中获取焦点android.view.View。默认情况下,弹出窗口不可聚焦。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()。
open Unit setHeight(height: Int)设置弹出窗口的请求高度。可能是布局常量,例如LayoutParams#WRAP_CONTENTLayoutParams#MATCH_PARENT。弹出窗口的实际大小可能取决于其他因素,例如剪辑和窗口布局。
open Unit setIgnoreCheekPress()在弹出窗口中设置标志以忽略脸颊按压事件;默认情况下,此标志设置为 false,这意味着弹出窗口不会忽略脸颊按下调度事件。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()。如果正在显示弹出窗口,则调用此方法将在下次显示弹出窗口时生效。
open Unit setInputMethodMode(mode: Int)控制弹出与输入方法如何运作:一INPUT_METHOD_FROM_FOCUSABLEINPUT_METHOD_NEEDEDINPUT_METHOD_NOT_NEEDED。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setIsClippedToScreen(enabled: Boolean)将此弹出窗口剪辑到屏幕,但不要剪辑到包含窗口。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setIsLaidOutInScreen(enabled: Boolean)允许弹出窗口强制标记WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN,覆盖默认行为。这将导致弹出窗口定位在绝对屏幕坐标中。
open Unit setOnDismissListener(onDismissListener: PopupWindow.OnDismissListener!)设置在窗口关闭时要调用的侦听器。
open Unit setOutsideTouchable(touchable: Boolean)控制是否将弹出窗口通知其窗口外的触摸事件。这仅对可触摸但不可聚焦的弹出窗口有意义,这意味着窗口外的触摸将传递到后面的窗口。默认值为假。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setOverlapAnchor(overlapAnchor: Boolean)设置弹出窗口在显示为下拉菜单时是否与其锚视图重叠。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时生效。
open Unit setSoftInputMode(mode: Int)设置软输入区域的操作模式。
open Unit setSplitTouchEnabled(enabled: Boolean)允许弹出窗口在也支持拆分触摸的其他窗口之间拆分触摸。当该标志为假时,第一个下降的指针决定了所有后续触摸所到的窗口,直到所有指针上升。当此标志为真时,下降的每个指针(不一定是第一个)确定该指针的所有后续触摸将转到的窗口,直到该指针上升,从而使具有多个指针的触摸能够跨多个窗口拆分。
open Unit setTouchInterceptor(l: View.OnTouchListener!)为分派到弹出窗口的所有触摸事件设置回调。
open Unit setTouchModal(touchModal: Boolean)设置此窗口是触摸模式还是外部触摸将发送到它后面的其他窗口。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setTouchable(touchable: Boolean)更改弹出窗口的可触摸性。当可触摸时,窗口将接收触摸事件,否则触摸事件将转到其下方的窗口。默认情况下,窗口是可触摸的。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时或通过手动调用其中一个方法时生效update()
open Unit setWidth(width: Int)设置弹出窗口的请求宽度。可能是布局常量,例如LayoutParams#WRAP_CONTENTLayoutParams#MATCH_PARENT。弹出窗口的实际大小可能取决于其他因素,例如剪辑和窗口布局。如果正在显示弹出窗口,则调用此方法将在下次显示弹出窗口时生效。
open Unit setWindowLayoutMode(widthSpec: Int, heightSpec: Int)更改由弹出窗口提供给窗口管理器的宽度和高度测量规格。默认情况下,它们是 0,这意味着当前宽度或高度被请求为来自窗口管理器的显式大小。您可以提供ViewGroup.LayoutParams#WRAP_CONTENTViewGroup.LayoutParams#MATCH_PARENT改为提供该度量规范,替换已在弹出窗口中设置的绝对宽度和高度。 弃用:使用setWidth(int)setHeight(int)。如果正在显示弹出窗口,则调用此方法只会在下次显示弹出窗口时生效。
open Unit setWindowLayoutType(layoutType: Int)设置此窗口的布局类型。
open Unit showAsDropDown(anchor: View!)在锚定于锚点视图左下角的弹出窗口中显示内容视图。如果屏幕上没有足够的空间来完整显示弹出窗口,则此方法会尝试找到要滚动的父滚动视图。如果没有父滚动视图可以滚动,则弹出窗口的左下角固定在锚视图的左上角。
open Unit showAsDropDown(anchor: View!, xoff: Int, yoff: Int)在锚定到锚定视图左下角的弹出窗口中显示内容视图,偏移指定的 x 和 y 坐标。如果屏幕上没有足够的空间来完整显示弹出窗口,则此方法会尝试找到要滚动的父滚动视图。如果没有父滚动视图可以滚动,则弹出窗口的左下角固定在锚视图的左上角。如果视图稍后滚动移动anchor到不同的位置,则弹出窗口将相应地移动。
open Unit showAsDropDown(anchor: View!, xoff: Int, yoff: Int, gravity: Int)在锚定到另一个视图角落的弹出窗口中显示内容视图。窗口根据指定的重力定位并偏移指定的 x 和 y 坐标。如果屏幕上没有足够的空间来完整显示弹出窗口,则此方法会尝试找到要滚动的父滚动视图。如果没有父视图可以滚动,指定的垂直重力将被忽略,弹出窗口将自身锚定,使其可见。如果视图稍后滚动移动anchor到不同的位置,则弹出窗口将相应地移动。
open Unit showAtLocation(parent: View!, gravity: Int, x: Int, y: Int)在指定位置的弹出窗口中显示内容视图。如果弹出窗口无法适应屏幕,它将被剪裁。有关android.view.WindowManager.LayoutParams重力与 x 和 y 参数如何相关的更多信息,请参见。指定重力android.view.Gravity#NO_GRAVITY类似于指定`Gravity.LEFT Gravity.TOP`。
open Unit update()从当前设置的状态更新弹出窗口的状态(如果当前正在显示)。
open Unit update(width: Int, height: Int)更新弹出窗口的尺寸。setClippingEnabled(boolean) ,setFocusable(boolean),setIgnoreCheekPress(),setInputMethodMode(int),setTouchable(boolean),setAnimationStyle(int) ,setTouchModal(boolean),setIsClippedToScreen(boolean)
open Unit update(x: Int, y: Int, width: Int, height: Int)更新弹出窗口的位置和尺寸。宽度和高度可以设置为 -1 以仅更新位置。调用此函数还会使用当前弹出状态更新窗口,如 中所述update()。
open Unit update(x: Int, y: Int, width: Int, height: Int, force: Boolean)更新弹出窗口的位置和尺寸。宽度和高度可以设置为 -1 以仅更新位置。调用此函数还会使用当前弹出状态更新窗口,如 中所述update()
open Unit update(anchor: View!, width: Int, height: Int)更新弹出窗口的位置和尺寸。调用此函数还会使用当前弹出状态更新窗口,如 中所述update()
open Unit update(anchor: View!, xoff: Int, yoff: Int, width: Int, height: Int)更新弹出窗口的位置和尺寸。宽度和高度可以设置为 -1 以仅更新位置。调用此函数还会使用当前弹出状态更新窗口,如 中所述update()。如果视图稍后滚动移动anchor到不同的位置,则弹出窗口将相应地移动。

activity_main.xml

class MyPopupWindow(val context: Context, width: Int, height: Int) : PopupWindow(width, height) {
    var binding: LayoutPopupBinding

    init {
        isFocusable = true
        isOutsideTouchable = true
        elevation = 10.0F
        val view = LayoutInflater.from(context).inflate(R.layout.layout_popup, null)
        contentView = view
        binding = LayoutPopupBinding.bind(view)
        binding.textView.setOnClickListener {
            Toast.makeText(context, "点击了弹窗中的按钮", Toast.LENGTH_SHORT).show()
        }
    }
}

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.textView.setOnClickListener {
            val popupWindow = MyPopupWindow(this, 600, 600)
            popupWindow.showAsDropDown(it,-(300 - it.width/2),0)
        }
    }
}
截屏2021-09-02 上午9.40.33.png

Dialog Activity

class PopActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //这段代码必须在setContentView之前
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.activity_pop)
    }
}
<activity
            android:name=".PopActivity"
            android:exported="true"
            android:theme="@style/PopActivity"
            />
           
<style name="PopActivity" parent="Theme.AppCompat.Dialog">
        <!-- 设置宽度 -->
        <item name="windowMinWidthMinor">80%</item>
              <!-- 设置高度 -->
        <item name="android:minHeight">300dp</item>
        <!-- 设置背景 -->
        <item name="android:windowBackground">#00000000</item>
</style>
截屏2021-09-02 上午10.33.16.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容