当前位置: 首页 > 工具软件 > PopView > 使用案例 >

PopupWindow最全使用说明

曾嘉荣
2023-12-01

本文将用以下几类做介绍:

  1. 可以用来做什么
  2. 使用方法
  3. 属性
  4. 理论知识
  • 可以用来做什么

PopupWindow可以在窗口的任意位置显示,相对于其它窗口组件显示的位置更灵活,Popupwindow不会给页面的其它部分添加蒙层(可通过代码自定义添加)

  • 使用方法

常用属性设置
View popView = LayoutInflater.from(context).inflate(R.layout.dialog_wheel_select, null);
            PopupWindow popWindow = new PopupWindow(popView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            //dismiss时的回调事件
            popWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    WindowUtils.setBackgroundAlpha(context, 1.0f);
                }
            });
            //设置popupWindow的显示和隐藏动画
            popWindow.setAnimationStyle(R.style.WheelSelect);
            //这个函数不止能设置背景,加上它之后setOutsideTouchable()才会生效;而且只有加上它之后,点击手机返回按钮才可以关闭PopupWindow,否则响应的是对应Activity
            popWindow.setBackgroundDrawable(new ColorDrawable());
            //设置PopupWindow是否响应touch事件,默认是true,如果为false,所有按钮不可点击
            popWindow.setTouchable(true);
            //是否可获取焦点,设置为true会响应back键的返回,同时拥有setOutsideTouchable(true)的作用.
            popWindow.setFocusable(true);
            //其它区域添加蒙色背景
            WindowUtils.setBackgroundAlpha(context, 0.5f);
            //设置显示位置
            popWindow.showAtLocation(popView, Gravity.BOTTOM, 0, 0);
WindowUtils通过代码添加蒙层(显示窗口前调用):

    private static void applyDim(Activity activity, float bgAlpha) {
        if (Build.VERSION.SDK_INT >= 18) {
            ViewGroup parent = (ViewGroup) activity.getWindow().getDecorView().getRootView();
            Drawable dim = new ColorDrawable(-16777216);
            dim.setBounds(0, 0, parent.getWidth(), parent.getHeight());
            dim.setAlpha((int) (255.0F * bgAlpha));
            ViewGroupOverlay overlay = parent.getOverlay();
            overlay.add(dim);
        }
    }
通过代码清除蒙层(销毁时调用):

    private static void clearDim(Activity activity) {
        if (Build.VERSION.SDK_INT >= 18) {
            ViewGroup parent = (ViewGroup) activity.getWindow().getDecorView().getRootView();
            ViewGroupOverlay overlay = parent.getOverlay();
            overlay.clear();
        }
    }

    /**
     * 设置背景阴影(蒙色)
     *
     * @param mContext context
     * @param bgAlpha  1.0F为清除灰蒙背景,0.5F为添加蒙色
     */
    public static void setBackgroundAlpha(Context mContext, float bgAlpha) {
        if (bgAlpha == 1.0F) {
            clearDim((Activity) mContext);
        } else {
            applyDim((Activity) mContext, bgAlpha);
        }
    }
  • 属性

构造方法
PopupWindow ()
PopupWindow (View contentView)	 
PopupWindow (View contentView, int width, int height)
PopupWindow (View contentView, 	//PopupWindow的内容View, 相当于setContentView
                int width, 	// 宽, 相当于setwidth()
                int height,  // 高, 相当于setHeight
                boolean focusable) // 是否可获取焦点, 相当于setFocusable()
一般使用第三个和第四个构造函数,创建PopuWindow必须指定宽高,可使用LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
LinearLayout可替换为对应的布局文件类
调用显示的方式
//1.附着某个控件用showAsDropDown
//2.设置显示位置用showAtLocation
//showAsDropDown
void showAsDropDown (View anchor) // 弹窗显示在某个控件左下方
void showAsDropDown (View anchor, //显示在某个控件左下方
                int xoff,  //在依附控件为原点的X偏移坐标
                int yoff)  //在依附控件Y为原点的Y偏移坐标  
void showAsDropDown (View anchor, 
                int xoff, 
                int yoff, 
                int gravity)   //弹窗显示在控件的左下方还是右下方, 参数有Gravity.RIGHT/Gravity.LEFT. 默认是左下方
//showAsDropDown不存在Gravity.TOP或Gravity.BOTTOM效果

showAtLocation
//parent在某个控件左下方(只要是屏幕上任意控件对象即可)gravity相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移(0)
showAtLocation(View parent, int gravity, int x, int y):

需要注意的是多次调用show方法, 只会执行第一句

更新状态
//该方法不能更新PopupWindow的宽高, 只能更新参数的状态. 例如更新Focusable和OutsideTouchable
void update () 
更新宽高
void update (int width,int height)
更新显示位置
//该方法相当于重新执行showAsDropDown
void update (View anchor,int width,int height)
void update (View anchor, int xoff,int yoff, int width, int height)
相对位置偏移更新
//相对当前的位置进行偏移,窗口宽高
void update(int x, int y, int width, int height)
//相对偏移,窗口宽高,是否可获取焦点
void update (int x, int y, int width, int height, boolean force) 
其它函数
//销毁窗口
public void dismiss()
//是否具有获取焦点的能力,默认为False,一般来讲是没用的,因为普通控件不需要获取焦点,而对于EditText如果不能获取焦点,那么将无法编辑。
public void setFocusable(boolean focusable)
//设置PopupWindow是否响应touch事件,默认是true,如果为false,所有按钮不可点击
public void setTouchable(boolean touchable)
//如果点击PopupWindow以外的区域,PopupWindow是否会消失。
public void setOutsideTouchable(boolean touchable)
//这个函数不止能设置背景,加上它之后setOutsideTouchable()才会生效;而且只有加上它之后,点击手机返回按钮才可以关闭PopupWindow,否则响应的是对应Activity
public void setBackgroundDrawable(Drawable background)

不常用函数
//多点触控
void setSplitTouchEnabled (boolean enabled)
boolean isSplitTouchEnabled ()
//忽略CheekPress事件,当物体触摸在屏幕上的尺寸超过手指尺寸范围, 被判定为CheekPress事件(脸颊点击)//默认为false, 即不忽略
void setIgnoreCheekPress () 
//解决NavigationBar重叠,这是Android5.0(API22)后添加的方法, 默认为true. 为true时将不会与导航栏重叠.
void setAttachedInDecor (boolean enabled)
//遮盖附着View,如果为true对齐方式默认从View anchor的左下角变成了左上角了.
void setOverlapAnchor (boolean overlapAnchor)
boolean getOverlapAnchor ()
//窗口裁剪,PopupWindow默认是不会超出屏幕边界的. 但是如果该方法为false时会采用精准位置, 能超出屏幕范围.
void setClippingEnabled (boolean enabled)
boolean isClippingEnabled ()
//通过样式设置进出动画,传入一个Style的样式id
void setAnimationStyle (int animationStyle)
int getAnimationStyle ()
//style样式的进出动画
  <style name="popupwindow_anim_style">
    <item name="android:windowEnterAnimation">@anim/dialog_bottom_enter</item>
    <item name="android:windowExitAnimation">@anim/dialog_bottom_exit</item>
  </style>
//单独设置进入动画
void setEnterTransition (Transition enterTransition)
Transition getEnterTransition ()
//单独设置退出动画
void setExitTransition (Transition exitTransition)
Transition getExitTransition ()
//获取最大高度
int getMaxAvailableHeight (View anchor)
//控件Y轴偏移后可显示的最大高度
int getMaxAvailableHeight (View anchor,int yOffset) 
//api24增加的方法, 由于我手上没有7.0设备就不说了.
int getMaxAvailableHeight (View anchor, int yOffset, boolean ignoreBottomDecorations)
输入模式
//支持三种模式(一般用不到)
PopupWindow.INPUT_METHOD_FROM_FOCUSABLE 根据可否获取焦点判断是否可输入
PopupWindow.INPUT_METHOD_NEEDED 允许输入
PopupWindow.INPUT_METHOD_NOT_NEEDED 不允许输入
void setInputMethodMode (int mode)
int getInputMethodMode ()
软键盘模式
//九种取值, 可组合使用,分为两类:
//显示模式
PopupWindow.SOFT_INPUT_STATE_UNSPECIFIED 默认模式
PopupWindow.SOFT_INPUT_STATE_HIDDEN
PopupWindow.SOFT_INPUT_STATE_ALWAYS_HIDDEN 总是隐藏
PopupWindow.SOFT_INPUT_STATE_UNCHANGED
PopupWindow.SOFT_INPUT_STATE_VISIBLE
PopupWindow.SOFT_INPUT_STATE_ALWAYS_VISIBLE 自动弹出软键盘
//调整模式
PopupWindow.SOFT_INPUT_ADJUST_UNSPECIFIED 默认模式
PopupWindow.SOFT_INPUT_ADJUST_RESIZE 软键盘弹出后PopupWindow会自动调整坐标,不被遮挡
PopupWindow.SOFT_INPUT_ADJUST_PAN
//组合时赋值WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
void setSoftInputMode (int mode)
int getSoftInputMode ()

事件监听
//dismiss监听
void setOnDismissListener (PopupWindow.OnDismissListener onDismissListener)
//触摸事件拦截
void setTouchInterceptor (View.OnTouchListener l)
  • 设置进出动画

一.编写popupwindow的动画的xml文件
1、从底部退出动画pop_exit_anim.xml
<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
    <translate
        android:duration="420"
        android:fromYDelta="0"
        android:toYDelta="100%" />
</set>
2、从底部显示动画pop_enter_anim.xml
<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
 
    <translate
        android:duration="420"
        android:fromYDelta="100%"
        android:toYDelta="0" />
</set>
二.编写popupwindow动画的style,在styles.xml文件中设置一个动画样式
<style name="popwin_anim_style" parent="android:Animation"> 
    <item name="android:windowEnterAnimation">@anim/pop_enter_anim</item> 
    <item name="android:windowExitAnimation">@anim/pop_exit_anim</item> 
</style> 
三.在程序中为PopupWindow设置动画效果。
PopupWindow pop = new PopupWindow(view, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
pop.setAnimationStyle(R.style.popwin_anim_style);
  • 理论知识

PopupWindow必须设置View contentView,int width, int height,少任意一个就不能弹出来PopupWindow。
所以如果用Context构造函数来初始化,完整的代码应该是这样的:
View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null);
PopupWindwo popWnd = PopupWindow (context);
popWnd.setContentView(contentView);
popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
为什么要强制设置PopupWindow的Height、Width
布局的大小,应该是在它父布局的基础上决定的。父布局显示大小确定了以后,才能确定子布局文件的大小。
所以我们设置的宽高,就是给布局文件的父布局设置宽高。

 

 类似资料: