Android弹窗探究之PopupWindow的使用 您所在的位置:网站首页 安卓横屏动画延迟 Android弹窗探究之PopupWindow的使用

Android弹窗探究之PopupWindow的使用

2023-06-12 12:44| 来源: 网络整理| 查看: 265

相对于AlertDialog的使用,PopupWindow的使用也比较简单,这里主要介绍的是PopupWindow的基础使用包括在使用过程中的一些注意事项,做个笔记。

效果展示: 1.gif PopupWindow的基础方法 创建popupWindow实例 popupView = LayoutInflater.from(this).inflate(R.layout.popupwindow_view, null) popupWindow = PopupWindow() 设置展示的视图 // 设置PopupWindow装载的视图 // 也可以在创建popupWindow的时候直接设置进去 popupWindow?.contentView = popupView 设置宽度和高度 // 设置PopupWindow的宽高 // 1》自定义View的时候,最外层的布局设置的宽高无效 // 2》在外面必须手动设置宽度和高度,并且以外面设置的宽高为主 popupWindow?.width = ViewGroup.LayoutParams.WRAP_CONTENT popupWindow?.height = ViewGroup.LayoutParams.WRAP_CONTENT 设置外部区域可以点击取消popupWindow // 设置外部区域可以点击取消popupWindow popupWindow?.isOutsideTouchable = true 设置背景 // 设置PopupWindow的背景 popupWindow?.setBackgroundDrawable(resources.getDrawable(R.mipmap.ic_launcher)) 设置popupWindow是否可以聚焦 // 设置PopupWindow可以聚焦 // 如果不设置,在PopupWindow弹出的时候,点击返回键将直接退出Activity // 设置之后,在PopupWindow弹出的时候,点击返回键不会直接退出Activity而是关闭当前弹出的PopupWindow popupWindow?.isFocusable = true 设置弹窗弹出的动画高度 // 设置弹窗弹出的动画高度 popupWindow?.elevation = 100f 设置popupWindow是否可以触摸 // 设置PopupWindow可以触摸 popupWindow?.isTouchable = true 设置触摸监听 // 设置触摸监听 popupWindow?.setTouchInterceptor { _, _ -> Toast.makeText(this,"触发事件",Toast.LENGTH_SHORT).show() false } 设置取消事件监听 // 设置PopupWindow监听取消事件 popupWindow?.setOnDismissListener { Toast.makeText(this,"PopupWindow被关闭",Toast.LENGTH_SHORT).show() } PopupWindow的展示

方式一:

// 方法一:showAsDropDown(View anchor) // showAsDropDown(View anchor, int xoff, int yoff) // showAsDropDown(View anchor, int xoff, int yoff, int gravity) // anchor代表的是目标View,即参考的View // xoff,yoff 目标View的坐标偏移量 // int gravity 目标View的位置,默认为Gravity.TOP | Gravity.START,即以左上角为起始位置 popupWindow?.showAsDropDown(view,0,0, Gravity.BOTTOM)

方式二:

// 方法二:showAtLocation(View parent, int gravity, int x, int y) // View parent代表的是要能获取到window唯一标示的(也就是只要能获取到window 标示,view是什么控件都可以) // int gravity代表的是位置,即屏幕的上下左右,注意系统默认都是在屏幕中间 // int x, int y偏移量 popupWindow?.showAtLocation(view, Gravity.TOP, 0, 0)

当然,在实际的开发过程中我们并不能仅仅满足于如何简单使用,更多的时候我们需要去考虑兼容性与扩展性的问题,所以,在这里,我对PopupWindow做了一个简单的封装,如下所示:

简单封装

创建PopupWindow的管理类,即PopupWindowManager类

public class PopupWindowManager { // 设置默认的宽高 private int mPopupWindowWidth = ViewGroup.LayoutParams.MATCH_PARENT; private int mPopupWindowHeight = ViewGroup.LayoutParams.WRAP_CONTENT; private MyPopupWindow mPopupWindow; private static volatile PopupWindowManager mInstance; /** * 通过懒汉式来构建PopupWindowManager * * @return PopupWindowManager实例对象 */ public static PopupWindowManager getInstance() { if (mInstance == null) { synchronized (PopupWindowManager.class) { if (mInstance == null) { mInstance = new PopupWindowManager(); } } } return mInstance; } /** * 设置私有的构造函数 */ private PopupWindowManager() { mPopupWindow = new MyPopupWindow(); } /** * 获取PopupWindow的实例 * * @return PopupWindow */ private PopupWindow getMyPopupWindow() { return mPopupWindow; } /** * 初始化设置(默认宽高) * * @return PopupWindowManager实例对象 */ public PopupWindowManager init(View contentView) { return init(contentView, mPopupWindowWidth, mPopupWindowHeight); } /** * @param contentView 加载的View * @param width 设置的宽度 * @param height 设置的高度 * @return PopupWindowManager实例对象 * 默认情况下:(1)popupWindow点击外部区域可以关闭 * (2)popupWindow可以聚焦 * // 设置PopupWindow可以聚焦 * // 如果不设置,在PopupWindow弹出的时候,点击返回键将直接退出Activity * // 设置之后,在PopupWindow弹出的时候,点击返回键不会直接退出Activity而是关闭当前弹出的PopupWindow * (3)popupWindow弹出的动画高度为0 * (4)popupWindow内容区域可以触摸 */ public PopupWindowManager init(View contentView, int width, int height) { this.mPopupWindowWidth = width; this.mPopupWindowHeight = height; mPopupWindow.setContentView(contentView); mPopupWindow.setOutsideTouchable(true); mPopupWindow.setFocusable(true); mPopupWindow.setElevation(0); mPopupWindow.setTouchable(true); setBackgroundDrawable(); mPopupWindow.setWidth(mPopupWindowWidth); mPopupWindow.setHeight(mPopupWindowHeight); mPopupWindow.setAnimationStyle(R.style.popup_window_anim_style); return this; } /** * 设置popupWindow的背景 * * @return PopupWindowManager实例对象 */ private PopupWindowManager setBackgroundDrawable() { ColorDrawable dw = new ColorDrawable(Color.parseColor("#50000000")); mPopupWindow.setBackgroundDrawable(dw); return this; } /** * 设置popupWindow的背景 * * @param color 设置的背景颜色 * @return PopupWindowManager实例对象 */ public PopupWindowManager setBackgroundDrawable(int color) { ColorDrawable dw = new ColorDrawable(color); mPopupWindow.setBackgroundDrawable(dw); return this; } /** * 设置popupWindow的动画效果 * @param animationStyle 动画样式 * @return PopupWindowManager实例对象 */ public PopupWindowManager setAnimationStyle(int animationStyle){ mPopupWindow.setAnimationStyle(animationStyle); return this; } /** * 设置popupWindow点击外部区域是否可以关闭 * * @param isOutsideTouchable true代表可以关闭 false代表不可以关闭 * @return PopupWindowManager实例对象 */ public PopupWindowManager setOutsideTouchable(boolean isOutsideTouchable) { mPopupWindow.setOutsideTouchable(isOutsideTouchable); return this; } /** * popupWindow是否可以聚焦 * * @param isFocusable true代表可以聚焦 false代表不可以聚焦 * @return PopupWindowManager实例对象 */ public PopupWindowManager setFocusable(boolean isFocusable) { mPopupWindow.setFocusable(isFocusable); return this; } /** * 设置popupWindow弹出的动画高度 * * @param elevation 高度 * @return PopupWindowManager实例对象 */ public PopupWindowManager setElevation(float elevation) { mPopupWindow.setElevation(elevation); return this; } /** * 设置popupWindow内容区域是否可以触摸 * * @param touchable true代表可以触摸 false代表不可以触摸 * @return PopupWindowManager实例对象 */ public PopupWindowManager setTouchable(boolean touchable) { mPopupWindow.setTouchable(touchable); return this; } /** * 设置关闭PopupWindow的监听 * * @param onDismissListener 设置的监听实例 * @return PopupWindowManager实例对象 */ public PopupWindowManager setOnDismissListener(PopupWindow.OnDismissListener onDismissListener) { mPopupWindow.setOnDismissListener(onDismissListener); return this; } /** * 在PopupWindow弹出之后点击任意区域关闭 * * @param listener 设置的监听实例 * @return PopupWindowManager实例对象 */ public PopupWindowManager setTouchInterceptor(View.OnTouchListener listener) { mPopupWindow.setTouchInterceptor(listener); return this; } /** * 在指定视图的下方展示 * * @param anchor 目标View * 一般情况下展示的视图以目标View的左下方的位置作为锚点 */ public void showAsDropDown(View anchor) { mPopupWindow.showAsDropDown(anchor); } /** * 在指定视图的下方展示 * * @param anchor 目标View * @param xoff x轴的偏移量 * @param yoff y轴的偏移量 */ public void showAsDropDown(View anchor, int xoff, int yoff) { mPopupWindow.showAsDropDown(anchor, xoff, yoff); } /** * 在指定视图的下方展示 * * @param anchor 目标View * @param xoff x轴的偏移量 * @param yoff y轴的偏移量 * @param gravity 相对于View的定位,系统默认是Gravity.TOP | Gravity.START; */ public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) { mPopupWindow.showAsDropDown(anchor, xoff, yoff, gravity); } /** * 以绝对值(x,y)来进行显示 * * @param parent View parent代表的是要能获取到window唯一标示的(也就是只要能获取到window 标示,view是什么控件都可以) * @param gravity int gravity代表的是位置,即屏幕的上下左右,注意系统默认都是在屏幕中间 * @param x x轴的偏移量 * @param y y轴的偏移量 */ public void showAtLocation(View parent, int gravity, int x, int y) { mPopupWindow.showAtLocation(parent, gravity, x, y); } /** * 关闭PopupWindow */ public void close() { if (mPopupWindow != null && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); } } }

新建类来继承自PopupWindow

public class MyPopupWindow extends PopupWindow { @Override public void showAsDropDown(View anchor) { handlerHeight(anchor); super.showAsDropDown(anchor); } @Override public void showAsDropDown(View anchor, int xoff, int yoff) { handlerHeight(anchor); super.showAsDropDown(anchor, xoff, yoff); } @Override public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) { handlerHeight(anchor); super.showAsDropDown(anchor, xoff, yoff, gravity); } /** * 解决高度无法自适应的问题 */ private void handlerHeight(View anchor) { if (Build.VERSION.SDK_INT >= 24) { Rect rect = new Rect(); anchor.getGlobalVisibleRect(rect); int heightPixels = anchor.getResources().getDisplayMetrics().heightPixels; int h = heightPixels - rect.bottom + getStatusHeight(anchor.getContext()); setHeight(h); } } /** * 获取状态栏的高度 */ private int getStatusHeight(Context context) { int statusHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } }

最后进行调用:

val popView = LayoutInflater.from(this).inflate(R.layout.pop_view, null) PopupWindowManager.getInstance().init(popView).setOnDismissListener { PopupWindowManager.getInstance().close() }.setTouchInterceptor { v, event -> PopupWindowManager.getInstance().close() false }.showAsDropDown(view)

到这里,popupWindow的简单使用就完成了。最后来讲一下在使用popupWindow的过程中需要注意的几点。

注意事项

(1)必须手动给popupWindow设置宽度和高度,否则popupWindow不显示。 (2)在手机系统的API大于24的时候全屏展示的时候会完全填充整个屏幕,而不是在目标View的下方正常显示。 (3)在有些手机上面,全屏展示的时候底部会留白,其实是因为StatusBar的高度没有计算进去,需要我们自己手动计算出去。 (4)当我们设置了setFocusable为true的时候,点击屏幕事件会交由onTouchListener处理。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有