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. bash variables plus operator All In One

    bash variables plus operator All In One Errors missing pass params #!/usr/bin/env bash # echo emoji ...

  2. Dart SDK All In One

    Dart SDK All In One Dart SDK archive https://dart.dev/tools/sdk/archive https://dart.dev/get-dart Th ...

  3. website & blogs & about me & contact

    website & blogs & about me & contact demos https://davidwalsh.name/about-david-walsh htt ...

  4. array auto slice

    array auto slice https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Ar ...

  5. Headless Chrome

    Headless Chrome https://developers.google.com/web/updates/2017/04/headless-chrome Puppeteer & SS ...

  6. how to change svg polygon size by update it's points in js

    how to change svg polygon size by update it's points in js matrixTransform https://stackoverflow.com ...

  7. Nestjs 上传文件到七牛云

    $ npm install qiniu import * as url from 'url'; import * as qiniu from 'qiniu'; @Post('upload') @Use ...

  8. DeFi下半场,除了YFI,还有BGV!

    自今年夏季开始,DeFi市场便已经进入火热态势,且持续至今.其中,去中心化交易所(DEX)以及各种金融衍生品的出现,吸引了大批资金的进入,资本市场的目光已从传统金融移到了DeFi市场,期望着能够从De ...

  9. 教你吃透CSS的盒子模型(Box Model)

    CSS 盒子模型(Box Model) 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封装周围的H ...

  10. 深入理解Java内存模型JMM

    本文转载自深入理解Java内存模型JMM JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执 ...