Android 开发学习进程0.30 builder模式创建popwindow
builder模式创建自定义popwindow
builder设计模式
将一个复杂的对象构建与它的表示分离,简化代码的使用方式。当对象有多个参数或多个零件同时初始化方法同时初始化方法有默认值时,采用此模式比较方便。
主要结构
- basepopwindow 产品类
- builder 产品类具体的构造类 basepopwindow的子类
- BasePopController 产品类控制类
- 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.animationResId);
            }
            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);
Android 开发学习进程0.30 builder模式创建popwindow的更多相关文章
- Android 开发学习进程0.16   layout_weight属性  R文件关联XML  Module
		layout_weight属性 layout_weight属性我们常常用到,但有时候会发现它还有一些奇怪的属性,比如大多数使用时会把宽度设置成0,但要是宽度不设置成0会有什么效果? layout_we ... 
- Android 开发学习进程0.19  webview 的使用
		Android 中的webview android 中的webview是可以在app内部打开HTML等的网页,不必再打开浏览器,有两种实现方法,即webviewclient webChromeclie ... 
- Android开发学习进程0.18  SharePreference的使用 AIDL
		SharePreference SharePreference是一种持久化存储手段,使用场景很多,如第一次打开时加载的用户协议等.适合小数据单进程的应用.将数据以键值对的形式存储在XML中. 使用方式 ... 
- Android 开发学习进程0.17   Android资源文件selector  textview显示两种不同字体
		selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ... 
- Android 开发学习进程0.15   adb cardview framelayout 控件设置状态获取焦点
		Android设备调试桥 即adb 使用adb进行无线调试的一些常用命令 adb tcpip 5555 设置调试端口为5555 防止冲突 adb shell ifconfig wlan0 查询局域网中 ... 
- Android 开发学习进程0.27  kotlin使用 和viewbinding的使用
		kotlin-android-extensions 插件被废弃 笔者曾经尝试写过一部分的kotlin代码 主要是项目中一些代码是kotlin完成的,其中我认为 kotlin的kotlin-androi ... 
- Android 开发学习进程0.28  腾讯TBS接入和相关问题
		TBS 的接入和使用 TBS 的接入 腾讯TBS是X5内核的升级版,可以当作webview 来打开 网页,可以以用来打开docx doc pdf 等文件,这里主要使用的是文件功能. 依赖接入 api ... 
- Android 开发学习进程0.32 dwonloadmanager使用
		downloadmanager时Android系统下载器,使用系统下载器可以避免用stream流读入内存可能导致的内存溢出问题.以下为downloadmanager初始化部分.apkurl为下载网络路 ... 
- Android 开发学习进程0.14    Bindview  recyclerview  popwindow使用  window类属性使用
		BindView ButterKnife 优势 绑定组件方便,使用简单 处理点击事件方便,如adapter中的viewholder 同时父组件绑定后子组件无需绑定 注意 在setcontentview ... 
随机推荐
- hihoCoder Challenge 3
			#1065 : 全图传送 时间限制:30000ms 单点时限:3000ms 内存限制:256MB 描述 先知法里奥是 Dota 系列中的一个英雄.机动性强,推塔能力一流,打钱速度快,传送技能使先知可以 ... 
- JavaScript var, let, const difference All In One
			JavaScript var, let, const difference All In One js var, let, const 区别 All In One 是否存在 hoisting var ... 
- Google coding Style Guide  : Google 编码风格/代码风格 手册/指南
			1 1 1 https://github.com/google/styleguide Google 编码风格/代码风格 手册/指南 Style guides for Google-originated ... 
- Promise nested then execute order All In One
			Promise nested then execute order All In One Promise nested then nested Promise not return new Promi ... 
- VS Code使用Git可视化管理源代码详细教程
			前言: 随着VS Code的功能和插件的不断强大和完善,它已经成为了我们日常开发中一个必不可缺的伙伴了.在之前我曾经写过一篇SourceTree使用教程详解(一个git可视化管理神器,想要了解的话可以 ... 
- 【Python】set 与 list ——如何对列表进行去重?
			在Python中,形如 {1,2,3,4,5} 这样的数据类型叫做"集合",外形酷似列表list [1,2,3,4,5] 但是集合与列表有很多区别,具体表现在以下几方面: List ... 
- Python算法_整数反转(02)
			给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123输出: 321 示例 2: 输入: -123输出: -321 示例 3: 输入: 120 输出: 2 ... 
- Flex实现左右布局
			html <div class="business-content-1"> <div class="item"> 111 </di ... 
- JVM基础入门
			内存模型 我理解的jvm: 个人理解的jvm流程: .java反编译为.class文件 经类加载器到上图的内存模型 方法区:存静态 常量区(String在里面) 本地栈区:调本地服务其它库的方法 计数 ... 
- Mybites学习
			参考链接:https://www.cnblogs.com/dongying/p/4073259.html <select <!-- 1. id (必须配置) id是命名空间中的唯一标识符, ... 
