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. HTML5 download 执行条件

    HTML5 download 执行条件 同一个域名下的资源 http only 绝对路径/相对路径 都可以 demo https://cdn.xgqfrms.xyz/ https://cdn.xgqf ...

  2. 抓手 & 技术管理

    抓手 & 技术管理 https://zhuanlan.zhihu.com/p/28891618 技术管理的目的 管理就是通过别人拿到结果.而管理的两个着眼点就是:成事.育人. 把事情搞定,把人 ...

  3. 基本ILS面的评估

    一.定义与用途 基本ILS面是ICAO DOC8168飞行程序设计规范中提到的一种限制面. 它相当于附件14中代码为3或4的精密进近跑道所规定的障碍物限制面的子集. 包含:进近面(分为两部分).过渡面 ...

  4. rabbitMQ高可用方案

    普通模式 默认的集群模式,以两个节点(rabbit01.rabbit02)为例来进行说明.对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和r ...

  5. oracle 中的左外连接、右外连接、全连接

    左外连接 左外连接 全连接1.左外连接:表1 left [outer] join 表1 on 条件 在等值连接的基础上会把表1中的其他内容也展示出来 而表2只会显示符合条件的内容 . outer 可省 ...

  6. day1 分布式基础概念

    1. 分布式:一个业务分拆多个子业务,部署在不同的服务器上集群:同一个业务,部署在多个服务器上节点:集群中的一个服务器 2.远程调用 分布式系统中调用其它主机 springcloud用http+jso ...

  7. Vue学习笔记-Vue.js-2.X 学习(一)===>基本知识学习

    一  使用环境: windows 7 64位操作系统 二  IDE:VSCode/PyCharm 三  Vue.js官网: https://cn.vuejs.org/ 四  下载安装引用 方式1:直接 ...

  8. TorchVision 预训练模型进行推断

    torchvision.models 里包含了许多模型,用于解决不同的视觉任务:图像分类.语义分割.物体检测.实例分割.人体关键点检测和视频分类. 本文将介绍 torchvision 中模型的入门使用 ...

  9. socket短连接太多,accept次数很多导致主线程CPU占满,工作线程CPU占用率低

    1.使用epoll的ET模式: 2.开启reuseport方法: Linux 最新SO_REUSEPORT特性:http://www.mamicode.com/info-detail-2201958. ...

  10. 死磕Spring之IoC篇 - 开启 Bean 的加载

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...