首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Android】PopupWindow弹窗

【Android】PopupWindow弹窗

作者头像
三三是该溜子
发布2025-08-23 08:17:53
发布2025-08-23 08:17:53
13000
代码可运行
举报
文章被收录于专栏:该溜子的专栏该溜子的专栏
运行总次数:0
代码可运行

一:需求及总代码

我们使用AlertDialog的时候一般不会去改变它的位置(默认居中),如果我们想去指定一个在任意位置显示的弹窗,可以使用Popup Window,它对于位置的控制会更加灵活

点击显示一个底部弹窗按钮,出现下图效果,点击弹窗外界,关闭弹窗

代码语言:javascript
代码运行次数:0
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".popupwindow.PopupWindowActivity">

    <Button
        android:id="@+id/btn_show_bottom_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:text="显示一个底部弹窗"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
代码语言:javascript
代码运行次数:0
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:padding="16dp">

    <Button
        android:id="@+id/btn_show_simple"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="测试按钮1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <Button
        android:id="@+id/btn_show_dialog_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="测试按钮2"

        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_show_simple" />

    <Button
        android:id="@+id/btn_show_auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="测试按钮3"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_show_dialog_fragment" />


</androidx.constraintlayout.widget.ConstraintLayout>
代码语言:javascript
代码运行次数:0
运行
复制
public class PopupWindowActivity extends AppCompatActivity {

    private PopupWindow popupWindow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_popup_window);

        ConstraintLayout parent = findViewById(R.id.main);

        findViewById(R.id.btn_show_bottom_menu).setOnClickListener(view ->{
            //显示在哪个根布局,位置,xy坐标
            popupWindow.showAtLocation(parent, Gravity.BOTTOM,0,0);
            setBackgroundAlpha(0.3f);
        });

        createBottomPopupWindow();

    }

    private void createBottomPopupWindow(){
        View view = getLayoutInflater().inflate(R.layout.layout_bottom_menu_popupwindow, null);
        popupWindow = new PopupWindow(view,
                ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);

        popupWindow.setOutsideTouchable(true);
        //如果弹窗消失,就把透明度修改回来
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                setBackgroundAlpha(1.0f);
            }
        });
    }

    private void setBackgroundAlpha(float f){
        WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
        layoutParams.alpha = f;
        getWindow().setAttributes(layoutParams);
    }
}

二:PopupWindow源码

PopupWindow弹窗,可以让我们对于弹窗位置的控制会更加灵活,

1:构造方法

构造方法的重载,最常用的是最后一种

两种写法创建PopupWindow,合在一起,分开都可以

代码语言:javascript
代码运行次数:0
运行
复制
		View view = getLayoutInflater().inflate(R.layout.layout_bottom_menu_popupwindow, null);
        popupWindow = new PopupWindow(view,
                ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);

三:代码分析

1:showAtLocation

这个方法就是把PopupWindow显示到当前某个布局当中;

xy偏移量;x正-整体往右移动,y正-整体往下移动;

偏移后不允许超出屏幕,所以很多时候偏移量是否生效,取决于Gravity以及当前弹窗布局的大小:比如当前布局宽度已经被设定为match_parent,所以x偏移量不会生效

代码语言:javascript
代码运行次数:0
运行
复制
		ConstraintLayout parent = findViewById(R.id.main);

        findViewById(R.id.btn_show_bottom_menu).setOnClickListener(view ->{
            //显示在哪个根布局,位置,xy坐标
            popupWindow.showAtLocation(parent, Gravity.BOTTOM,0,0);
            setBackgroundAlpha(0.3f);
        });

        createBottomPopupWindow();

2:细节

(1)PopupWindow根布局的高度

PopupWindow根布局的高度不要写成match_content(匹配父布局),PopupWindow的设计初衷是作为 “轻量级悬浮弹窗”,而非全屏视图。将其根布局高度设为match_parent会违背这一特性,导致显示异常、交互受阻等问题。使用**wrap_content**或精确指定高度,才能让PopupWindow的行为符合预期,避免隐藏的兼容性与用户体验问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(2)根布局返回类型

包不要导错了,用androidx下的包

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3:问题

(1)透明区域的设置
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(2)关闭弹窗后透明度还原
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(3)底部弹窗也变成透明

给根布局背景色设置为白色即可

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

效果对比

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4:setOutsideTouchable

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击外部区域,弹窗允许关闭;源码中默认值为false,更改为true

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5:setOnDismissLinstener

设置弹窗消失监听器

6:设置透明度

针对PopupWindow,一般来说我们是不用去针对空余位置设置半透明的,但是有些商业需求比较奇葩,

思路:当弹窗时,给空余区域加一个透明的样式;当关闭的时候,再把这个样式给关闭掉

Alpha透明度之前学过的,包括如何获取它,修改它,再把修改后的参数设置回去,这里用方法包装了一下

四:收获

PopupWindow的创建方式,怎么修改它的透明度,弹窗的监听器怎么样

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:需求及总代码
  • 二:PopupWindow源码
    • 1:构造方法
  • 三:代码分析
    • 1:showAtLocation
    • 2:细节
      • (1)PopupWindow根布局的高度
      • (2)根布局返回类型
    • 3:问题
      • (1)透明区域的设置
      • (2)关闭弹窗后透明度还原
      • (3)底部弹窗也变成透明
    • 4:setOutsideTouchable
    • 5:setOnDismissLinstener
    • 6:设置透明度
  • 四:收获
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档