建造者模式在android上的应用
其中AlertDialog就是一个例子,一般我们会这么用
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setXXX();
...
builder.create().show();
同理类似的还有Notification.Builder、StringBuilder等等,之前用过的一些第三方SDK都有见到过这种方式
今天心血来潮,项目中有很多地方用到PopupWindow,考虑到样式什么的都不是完全统一的,每次创建的时候有点麻烦,于是乎想到做一个包装类
下边代码注释比较详细就不做解释了,提一点,PopupParams中的apply方法是具体设置PopupWindow的地方,但是其显示要延迟到show方法中去做,自定义填充的view也要抛出来,以便在create之后外部可以拿到view,从中查找到需要的子view对象进行操作
其中封装了比较常用的设置,还有些没有封装到,若需要可以自己扩展
代码实现
MyPopupWindow.java
/**
* Created by yy on 2015/11/20.
* 自定义PopupWindow
* 使之以类似AlertDialog的方式建造生成并显示
*/
public class MyPopupWindow extends PopupWindow {
/**
* MyPopupWindow的控制类,持有一些必要的引用,同时可以参与控制PopupWindow
*/
private MyPopupControler mControler;
/**
* @param context 必须为Activity
* @param params 可设置PopupWindow的一些参数,根据需要以后可以扩展{@link PopupParams}
*/
private MyPopupWindow(Context context, PopupParams params) {
mControler = new MyPopupControler(((Activity) context).getWindow(), this, params);
}
/**
* 可设置PopupWindow的一些参数,根据需要以后可以扩展
*/
static class PopupParams {
/**
* 在BUilder过程是否设置了动画{@link MyPopupWindow.Builder#setAnimationStyle(int)}
*/
public boolean hasAnimationStyle = false;
public Context mContext;
/**
* PopupWindow的自定义样式,通常是一个xml资源文件
*/
public int mLayoutId;
/**
* 显示背景,默认全透明
*/
public Drawable mBackground;
/**
* 显示和隐藏的动画样式资源
*/
public int mAnimationStyle;
/**
* {@link PopupWindow#setFocusable(boolean)}
*/
public boolean mFocusable = true;
/**
* {@link PopupWindow#setOutsideTouchable(boolean)}
*/
public boolean mOutsideTouchable = true;
/**
* 默认宽高为包裹内容
* {@value LayoutParams#WRAP_CONTENT}
*/
public int mWidth = -99;
public int mHeight = -99;
/**
* 以下为{@link PopupWindow#showAtLocation(View, int, int, int)}的四个参数
* 其中mParent必须设置或者构造时指定
* mGravity默认为 {@value Gravity#CENTER}
* mOffsetX和mOffsetY默认为 0
*/
public View mParent;
public int mGravity = Gravity.CENTER;
public int mOffsetX = 0;
public int mOffsetY = 0;
/**
* 此项为了以后扩展使用LayoutParams而设置
*/
public WindowManager.LayoutParams mLayoutParams;
/**
* 显示PopupWindow时窗口背景的透明度,默认0.7
* 会覆盖mLayoutParams中的alpha
*/
public float mAlpha = 0.7f;
/**
* PopupWindow消失时回调
*/
public PopupWindow.OnDismissListener mOnDismissListener;
public PopupParams(Context context) {
mContext = context;
}
/**
* 在{@link Builder#create()}时将建造的PopupWindow参数保存应用到{@link MyPopupControler}
* 以便在{@link MyPopupWindow#show()}使用
*
* @param controler 操作对象
*/
public void apply(MyPopupControler controler) {
MyPopupWindow popupWindow = controler.getPopupWindow();
View view = View.inflate(mContext, mLayoutId, null);
controler.setView(view);
popupWindow.setContentView(view);
popupWindow.setWidth(mWidth == -99 ? -2 : DensityUtil.dip2px(mContext, mWidth));
popupWindow.setHeight(mHeight == -99 ? -2 : DensityUtil.dip2px(mContext, mHeight));
popupWindow.setBackgroundDrawable(mBackground == null ? new ColorDrawable(Color
.TRANSPARENT) : mBackground);
popupWindow.setFocusable(mFocusable);
popupWindow.setOutsideTouchable(mOutsideTouchable);
if (hasAnimationStyle)
popupWindow.setAnimationStyle(mAnimationStyle);
popupWindow.setOnDismissListener(mOnDismissListener == null ? new PopupWindow
.OnDismissListener() {
@Override
public void onDismiss() {
mLayoutParams.alpha = 1.0f;
((Activity) mContext).getWindow().setAttributes(mLayoutParams);
}
} : mOnDismissListener);
}
}
public static class Builder {
private Context mContext;
private PopupParams P;
public Builder(Context context) {
mContext = context;
P = new PopupParams(mContext);
}
public Builder(Context context, View parent) {
mContext = context;
P = new PopupParams(mContext);
P.mParent = parent;
}
public Builder setLayout(int layoutId) {
P.mLayoutId = layoutId;
return this;
}
public Builder setBackground(Drawable background) {
P.mBackground = background;
return this;
}
public Builder setAnimationStyle(int animationStyle) {
P.mAnimationStyle = animationStyle;
P.hasAnimationStyle = true;
return this;
}
public Builder setFocusable(boolean focusable) {
P.mFocusable = focusable;
return this;
}
public Builder setOutsideTouchable(boolean touchable) {
P.mOutsideTouchable = touchable;
return this;
}
public Builder setWidth(int width) {
P.mWidth = width;
return this;
}
public Builder setHeight(int height) {
P.mHeight = height;
return this;
}
public Builder setParent(View parent) {
P.mParent = parent;
return this;
}
public Builder setGravity(int gravity) {
P.mGravity = gravity;
return this;
}
public Builder setOffsetX(int offsetX) {
P.mOffsetX = offsetX;
return this;
}
public Builder setOffsetY(int offsetY) {
P.mOffsetY = offsetY;
return this;
}
public Builder setLayoutParams(LayoutParams layoutParams) {
P.mLayoutParams = layoutParams;
return this;
}
public Builder setAlpha(float alpha) {
P.mAlpha = alpha;
return this;
}
public Builder setOnDismissListener(OnDismissListener listener) {
P.mOnDismissListener = listener;
return this;
}
public MyPopupWindow create() {
final MyPopupWindow popupWindow = new MyPopupWindow(mContext, P);
P.apply(popupWindow.mControler);
return popupWindow;
}
public MyPopupWindow show() {
MyPopupWindow popupWindow = create();
popupWindow.showAtLocation(P.mParent, P.mGravity, P.mOffsetX, P.mOffsetY);
P.mLayoutParams = ((Activity) mContext).getWindow().getAttributes();
P.mLayoutParams.alpha = P.mAlpha;
((Activity) mContext).getWindow().setAttributes(P.mLayoutParams);
return popupWindow;
}
}
/**
* @return {@link Builder#create()}填充的自定义view
* @see PopupParams#apply(MyPopupControler)
*/
public View getView() {
if (mControler != null)
return mControler.getView();
else
return null;
}
/**
* 按照既定的参数显示PopupWindow
*
* @return 显示的PopupWindow
*/
public MyPopupWindow show() {
PopupParams p = mControler.getParams();
mControler.getPopupWindow().showAtLocation(p.mParent, p.mGravity, p.mOffsetX, p.mOffsetY);
p.mLayoutParams = mControler.getWindow().getAttributes();
p.mLayoutParams.alpha = p.mAlpha;
mControler.getWindow().setAttributes(p.mLayoutParams);
return mControler.getPopupWindow();
}
}
MyPopupControler.java
public class MyPopupControler {
/**
* Activity Window
*/
private Window mWindow;
/**
* 建造PopupWindow的参数
*/
private PopupParams P;
/**
* 要显示的PopupWindow
*/
private MyPopupWindow mPopupWindow;
/**
* 填充PopupWindow的自定义view
*/
private View mView;
public MyPopupControler(Window window, MyPopupWindow popupWindow, PopupParams params) {
mWindow = window;
P = params;
mPopupWindow = popupWindow;
}
public View getView() {
return mView;
}
public void setView(View view) {
mView = view;
}
public Window getWindow() {
return mWindow;
}
public PopupParams getParams() {
return P;
}
public MyPopupWindow getPopupWindow() {
return mPopupWindow;
}
}
应用场景片段
xml布局文件很简单只有一个TextView可以自己实现就好了,不再贴出了
popupWindow = new MyPopupWindow.Builder(this, parent)
.setLayout(R.layout.mypopuwindow)
.setAnimationStyle(R.style.Animation_AppCompat_DropDownUp)
.setWidth(320)
.setHeight(240)
.create();
View view = pwShopNotice.getView();
TextView tvContent = (TextView) view.findViewById(R.id.tv_content);
tvContent.setText("我是PopupWindow");
popupWindow.show();
理论补充:
建造者概念:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了“产品”是如何建造的,所以若需要改变一个“产品”的内部表示,只需再定义另一个Builder
迁移自CSDN
2015年11月20日 18:26:40
http://blog.csdn.net/u013262051/article/details/49950491
网友评论