Android 開發學習程序0.30 builder模式建立popwindow
阿新 • • 發佈:2021-03-25
# 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(poi