Android 开发学习进程0.30 builder模式创建popwindow

builder模式创建自定义popwindow

builder设计模式

将一个复杂的对象构建与它的表示分离,简化代码的使用方式。当对象有多个参数或多个零件同时初始化方法同时初始化方法有默认值时,采用此模式比较方便。

主要结构

  1. basepopwindow 产品类
  2. builder 产品类具体的构造类 basepopwindow的子类
  3. BasePopController 产品类控制类
  4. PopupParams 产品类参数类 basepopcontroller 的子类

代码实现

public class BasePopWindow extends PopupWindow {
    final BasePopController controller;

    public BasePopWindow(Context context) {
        this.controller = new BasePopController(context, this);
    }

    public interface ViewInterface{
        /**
         * view 或布局id
         * @param view
         * @param viewResId
         */
        void getChildView(View view,int viewResId);
    }
    @Override
    public int getWidth() {
        return controller.mPopWindowView.getMeasuredWidth();
    }
    @Override
    public int getHeight() {
        return controller.mPopWindowView.getMeasuredHeight();
    }

    @Override
    public void dismiss() {
        super.dismiss();
        controller.setAlpha(1.0f);
    }
    public static class Builder{
        private final BasePopController.PopupParams popupParams;
        private ViewInterface viewInterface;

        public Builder(Context context) {
            this.popupParams = new BasePopController.PopupParams(context);
        }
        /*
        返回this为链式调用
         */
        public Builder setView(int layoutResId){
            popupParams.mView=null;
            popupParams.layoutResId=layoutResId;
            return this;
        }
        public Builder setView(View mView){
            popupParams.mView=mView;
            popupParams.layoutResId=0;
            return this;
        }
        public Builder setConstomViewClickListen(ViewInterface viewInterface){
            this.viewInterface=viewInterface;
            return this;
        }
        public Builder setAnimation(int animationResId){
            popupParams.isAnimation=true;
            popupParams.animationResId=animationResId;
            return this;
        }
        public Builder setWidthHeight(int width,int height){
            popupParams.mWidth=width;
            popupParams.mHight=height;
            return this;
        }
        public Builder setAlpha(float alpha){
            popupParams.alpha=alpha;
            popupParams.isShowBg=true;
            return this;
        }
        public Builder setIsOutClick(boolean isOutClick){
            popupParams.isOutside=isOutClick;
            return this;
        }
        public BasePopWindow create(){
            final BasePopWindow window=new BasePopWindow(popupParams.context);
            popupParams.apply(window.controller);
            if (viewInterface!=null&& popupParams.layoutResId!=0) {
                viewInterface.getChildView(window.controller.mPopWindowView,popupParams.layoutResId);
            }
            int widthMeasureSpec=View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            int heightMeasureSpec=View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            window.controller.mPopWindowView.measure(widthMeasureSpec,heightMeasureSpec);
            return window;
        }
    }
}

basepopwindow 构造函数使用basepopcontroller完成,可以采用布局id或view两种参数之一,viewinterface 暴漏其中的子view,同时builder类设置参数的返回值均为this便于使用链式调用,
create方法组装basepopcontroller中的默认构造函数和popupparams中设置的参数,basepopcontroller代码如下:

public class BasePopController {
    private int layoutResId;
    private Context context;
    private PopupWindow popupWindow;
    View mPopWindowView;
    private View mView;
    private Window window;

    public BasePopController(Context context, PopupWindow popupWindow) {
        this.context = context;
        this.popupWindow = popupWindow;
    }
    public void setView(int layoutResId){
        mView=null;
        this.layoutResId=layoutResId;
        installContent();
    }
    public void setView(View mView){
        layoutResId=0;
        this.mView=mView;
        installContent();
    }

    private void installContent() {
        if (layoutResId != 0) {
            mPopWindowView= LayoutInflater.from(context).inflate(layoutResId, null);
        } else if (mView!=null){
            mPopWindowView=mView;
        }
        popupWindow.setContentView(mPopWindowView);
    }
    private void setWidthHeight(int width,int height){
        if (width==0) {
            popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
        } else {
            Log.e("popwindow", "setWidthHeight: "+width);
            popupWindow.setWidth(width);
        }
        if (height==0) {
            popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        } else {
            popupWindow.setHeight(height);
            Log.e("popwindow", "setWidthHeight: "+height);
        }
    }

    void setAlpha(float alpha){
        window= ((Activity)context).getWindow();
        WindowManager.LayoutParams lp=window.getAttributes();
        lp.alpha=alpha;
        window.setAttributes(lp);
    }
    private void setAnimation(int animaResId){
        popupWindow.setAnimationStyle(animaResId);
    }

    /**
     * 设置外部可点击
     */
    private void setOutsideClick(boolean isClick){
        popupWindow.setBackgroundDrawable(new ColorDrawable(context.getResources().getColor(R.color.transparent)));
        popupWindow.setOutsideTouchable(isClick);
        popupWindow.setFocusable(isClick);
    }
    static class PopupParams{
        public int layoutResId;
        public Context context;
        public int mWidth,mHight;
        public boolean isShowBg,isAnimation;
        public float alpha;
        public int animationResId;
        public View mView;
        public boolean isOutside;

        public PopupParams(Context context) {
            this.context = context;
        }

        public void apply(BasePopController controller){
            if (mView != null) {
                controller.setView(mView);
            }else if (layoutResId!=0){
                controller.setView(layoutResId);
            }else {
                throw new IllegalArgumentException("popwindow layout content no set");
            }
            controller.setWidthHeight(mWidth, mHight);
            controller.setOutsideClick(isOutside);
            if (isShowBg) {
                controller.setAlpha(alpha);
            }
            if (isAnimation) {
                controller.setAnimation(animationResId);
            }
        }
    }

}

具体使用方法如下:

  basePopWindow = new BasePopWindow.Builder(this)
                .setView(R.layout.bg_pop_actpaymentchose)
                .setWidthHeight((int) (point.x * 0.6), point.y / 4)
                .setAnimation(R.style.pop_bottom_anim)
                .setAlpha(0.5f)
                .setIsOutClick(true)
                .setConstomViewClickListen((view, viewResId) -> {
					//此处获取子view
                    tvleft.setOnClickListener(v -> {
                        basePopWindow.dismiss();
                    });
                    tvRight.setOnClickListener(v -> {
                        try {
                            jsonObject.put("orderNum", orderNum);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        mPresentser.getConfirmreceiving(jsonObject.toString());
                        basePopWindow.dismiss();
                    });
                })
                .create();
        basePopWindow.showAtLocation(findViewById(R.id.rl_root), Gravity.CENTER, 0, 0);

showAtLocation 方法显示在组件某位置,showAsDropDown()方法可以设置于某一组件下方,一般在启动按钮。windowmanager的LayoutParams参数alpha可以设置灰度,弹出popwindow时可以设置背景变暗,范围是0 ~1f,
可以设置页面的根布局,point值是根据屏幕获取的实际大小百分比设置,避免布局出现错乱。方法如下:

Display display = getWindowManager().getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);
posted @ 2021-03-25 14:06  百密一疏  阅读(138)  评论(0编辑  收藏  举报