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

2021年09月16日 阅读数:2
这篇文章主要向大家介绍Android 开发学习进程0.30 builder模式建立popwindow,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

builder模式建立自定义popwindow

builder设计模式

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

主要结构

  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);
            }
        }
    }

}

具体使用方法以下:app

  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值是根据屏幕获取的实际大小百分比设置,避免布局出现错乱。方法以下:ide

Display display = getWindowManager().getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);