Android开发-封装一个PopupWindow

4,103 阅读2分钟

前言

我们都知道,Android 中的弹窗基本有两种,一种是AlertDialog,另一种是PopupWindowAlertDialog的显示位置是固定的,PopWindow 的显示位置是我们可以设置和调整的,因此,像项目中的一些场景如:某个功能的提示说明、点击按钮在按钮上方或者下方弹出菜单、新功能弹窗引导等。由于这些弹窗的位置不固定,因此都可以用PopupWindow来做。最近项目中也用到了PopupWindow弹窗功能,在写的过程中,发现虽然API比较简单,但是写一个PopupWindow,还是有点繁琐,很多重复代码,决定简单封装一下,以后添加一个弹窗就不用那么麻烦了,几行代码就搞定了。本篇文章是对项目中使用 PopupWindow做一个笔记和总结。

效果预览

先祭出效果图一看为先

popupWindow1.gif 以上示例展示了7个PopupWindow 使用场景

正常使用

一般我们配置一个 PopupWindow通常的套路如下:

 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View popUpView = inflater.inflate(R.layout.pop_select_num_spec, null, false);
        selectNumSpecPop = new PopupWindow(popUpView, LinearLayoutCompat.LayoutParams.MATCH_PARENT, LinearLayoutCompat.LayoutParams.WRAP_CONTENT);
        selectNumSpecPop.setOutsideTouchable(true);
        popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        //设置PopupWindow的动画效果
        selectNumSpecPop.setAnimationStyle(R.style.anim_popUpWindow_bottom);

然后我们还需要添加动画,监听back键等等,并且去findViewById来获取Pop内部的控件,然后,另外一个需要用到的时候,又得重复写,真心很累。

那么,封装之后的Pop如下:

 popupWindow = new CommonPopupWindow.Builder(getContext())
                .setView(R.layout.pop_window_device)
                .setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                .setAnimationStyle(R.style.pop_add)
                .setViewOnclickListener(this)
                .setOutsideTouchable(true)
                .setBackGroundLevel(0.5f)// 取值范围0.0f-1.0f 值越小越暗
                .builder();
        popupWindow.showAsDropDown(view);

通过Builder的形式来构建Pop,这种链式写法,有没有很熟悉,很简洁。 这里,我是把pop那些需要设置的属性,都封装在了一个自定义的Builder类中,便于自己去定义

封装工具类

/**
 * @author iwen大大怪
 * @create 2021/11/09 0:07
 */
public class CommonPopupWindow extends PopupWindow {
​
    public final PopupController controller;
​
    public CommonPopupWindow(PopupController controller) {
        this.controller = controller;
    }
​
    /**
     * 获取宽
     */
    @Override
    public int getWidth() {
        return controller.mPopupView.getMeasuredWidth();
    }
​
    /**
     * 获取高
     */
    @Override
    public int getHeight() {
        return controller.mPopupView.getMeasuredHeight();
    }
​
    /**
     * 隐藏
     */
    @Override
    public void dismiss() {
        super.dismiss();
        controller.setBackGroundLevel(1.0f);
    }
​
    /**
     * 查看界面
     */
    public interface ViewInterface {
        void getChildView(View view, int layoutResId);
    }
​
    /**
     * 构造方法
     *
     * @param context 上下文
     */
    private CommonPopupWindow(Context context) {
        controller = new PopupController(context, this);
    }
​
    /**
     * 使用建造者模式
     */
    public static class Builder {
​
        private final PopupController.PopupParams params;
​
        private ViewInterface listener;
​
        public Builder(Context context) {
            params = new PopupController.PopupParams(context);
        }
​
        /**
         * 设置PopupWindow
         *
         * @param layoutResId 布局ID
         * @return Builder
         */
        public Builder setView(int layoutResId) {
            params.mView = null;
            params.layoutResId = layoutResId;
            return this;
        }
​
        /**
         * 设置PopupWindow布局
         *
         * @param view View
         * @return Builder
         */
        public Builder setView(View view) {
            params.mView = view;
            params.layoutResId = 0;
            return this;
        }
​
        /**
         * 设置子View
         *
         * @param listener ViewInterface
         * @return Builder
         */
        public Builder setViewOnclickListener(ViewInterface listener) {
            this.listener = listener;
            return this;
        }
​
        /**
         * 设置宽度和高度 如果不设置 默认是wrap_content
         *
         * @param width 宽
         * @return Builder
         */
        public Builder setWidthAndHeight(int width, int height) {
            params.mWidth = width;
            params.mHeight = height;
            return this;
        }
​
        /**
         * 设置背景灰色程度
         *
         * @param level 取值范围:0.0f-1.0f 值越小越暗
         * @return Builder
         */
        public Builder setBackGroundLevel(float level) {
            params.isShowBg = true;
            params.bg_level = level;
            return this;
        }
​
        /**
         * 是否可点击Outside消失
         *
         * @param touchable 是否可点击
         * @return Builder
         */
        public Builder setOutsideTouchable(boolean touchable) {
            params.isTouchable = touchable;
            return this;
        }
​
        /**
         * 设置动画
         *
         * @return Builder
         */
        public Builder setAnimationStyle(int animationStyle) {
            params.isShowAnim = true;
            params.animationStyle = animationStyle;
            return this;
        }
​
        public CommonPopupWindow builder(){
            final CommonPopupWindow popupWindow = new CommonPopupWindow(params.mContext);
            params.apply(popupWindow.controller);
            if (listener != null && params.layoutResId != 0){
                listener.getChildView(popupWindow.controller.mPopupView,params.layoutResId);
            }
            UIUtils.measureWidthAndHeight(popupWindow.controller.mPopupView);
            return popupWindow;
        }
​
    }
}

Github

github.com/ljr7822/And… 欢迎star