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.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的更多相关文章

  1. Android 开发学习进程0.16 layout_weight属性 R文件关联XML Module

    layout_weight属性 layout_weight属性我们常常用到,但有时候会发现它还有一些奇怪的属性,比如大多数使用时会把宽度设置成0,但要是宽度不设置成0会有什么效果? layout_we ...

  2. Android 开发学习进程0.19 webview 的使用

    Android 中的webview android 中的webview是可以在app内部打开HTML等的网页,不必再打开浏览器,有两种实现方法,即webviewclient webChromeclie ...

  3. Android开发学习进程0.18 SharePreference的使用 AIDL

    SharePreference SharePreference是一种持久化存储手段,使用场景很多,如第一次打开时加载的用户协议等.适合小数据单进程的应用.将数据以键值对的形式存储在XML中. 使用方式 ...

  4. Android 开发学习进程0.17 Android资源文件selector textview显示两种不同字体

    selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ...

  5. Android 开发学习进程0.15 adb cardview framelayout 控件设置状态获取焦点

    Android设备调试桥 即adb 使用adb进行无线调试的一些常用命令 adb tcpip 5555 设置调试端口为5555 防止冲突 adb shell ifconfig wlan0 查询局域网中 ...

  6. Android 开发学习进程0.27 kotlin使用 和viewbinding的使用

    kotlin-android-extensions 插件被废弃 笔者曾经尝试写过一部分的kotlin代码 主要是项目中一些代码是kotlin完成的,其中我认为 kotlin的kotlin-androi ...

  7. Android 开发学习进程0.28 腾讯TBS接入和相关问题

    TBS 的接入和使用 TBS 的接入 腾讯TBS是X5内核的升级版,可以当作webview 来打开 网页,可以以用来打开docx doc pdf 等文件,这里主要使用的是文件功能. 依赖接入 api ...

  8. Android 开发学习进程0.32 dwonloadmanager使用

    downloadmanager时Android系统下载器,使用系统下载器可以避免用stream流读入内存可能导致的内存溢出问题.以下为downloadmanager初始化部分.apkurl为下载网络路 ...

  9. Android 开发学习进程0.14 Bindview recyclerview popwindow使用 window类属性使用

    BindView ButterKnife 优势 绑定组件方便,使用简单 处理点击事件方便,如adapter中的viewholder 同时父组件绑定后子组件无需绑定 注意 在setcontentview ...

随机推荐

  1. Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3

    在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...

  2. Ajax 实战大全!

    1.html 文件 ( form.html) 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta http-equiv=& ...

  3. web 安全 & web 攻防: XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)

    web 安全 & web 攻防: XSS(跨站脚本攻击)和 CSRF(跨站请求伪造) XSS(跨站脚本攻击)和CSRF(跨站请求伪造) Cross-site Scripting (XSS) h ...

  4. nodemon all in one

    nodemon all in one https://nodemon.io/ https://github.com/remy/nodemon#nodemon https://www.npmjs.com ...

  5. vue技术栈

    1 vue 说明:vue生命周期:技术点:1:常用的API:computed,methods,props,mounted,created,components 2vue-cli说明:vue绞手架,用于 ...

  6. 「NGK每日快讯」2021.2.1日NGK公链第90期官方快讯!

  7. 破除区块链支付壁垒,NGK支付架构方案浮出水面

    什么叫做区块链支付?区块链支付系统与传统支付系统有哪些不同?简要地说,原来传统的支付系统是有一个类似于银行的中间平台存在的,用户们的支付交易第一时间是寄存在平台,由平台核实验证交易行为之后,方才放行交 ...

  8. 多种转弯角度的PBN旁切转弯图例分析

    无论世界怎样变化,我们依然是有点阳光就灿烂.面对世界的未知,最好的状态是勇敢的去面对,努力的去生活. 今天我们继续来聊一下PBN旁切转弯. PBN转弯保护区的结构通常都与它们的转弯角度大小有关,转弯角 ...

  9. Typescript快速入门

    目录 什么是Typescript 为什么学习Typescript 快速搭建开发环境 1.安装node.js 2.使用node自带的npm安装Typescript编译器 3.配置vscode编辑环境 4 ...

  10. 开源OA办公平台搭建教程:O2OA+Arduino实现物联网应用(二)

    O2OA平台搭建 O2OA的开发环境非常简单,安装服务器后即可通过浏览器进行开发了和使用.具体可参考文档库中的其他文档,有比较详细的介绍,这里就不再赘述了. Arduino开发发环境搭建 安装Ardu ...