java建造者模式在android上的实践

原创 2015年11月20日 18:26:40

java建造者模式在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

版权声明:本文为博主原创文章,转载请注明出处。

相关文章推荐

Android利用建造者模式自定义Dialog

  • 2016年03月10日 17:49
  • 3.52MB
  • 下载

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与[工厂方法模式](http://blog.csdn.net/self_study/...

java 建造者模式代码

  • 2017年01月03日 13:16
  • 12KB
  • 下载

建造者模式实践

建造者模式实践 本文翻译自:http://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html 我不打算跳入设计模...

java 建造者模式

  • 2011年12月25日 19:46
  • 2KB
  • 下载

Java/Android 设计模式<一> 单例模式+建造者模式

Java/Android 设计模式 android中的设计模式很多,可以有效提高开发效率,代码效率以及project新能; 1 单例模式:java/android中最常用的设计模式: pr...

java建造者(Builder)模式

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 类型:创建类模式 类图: 四个要素 产品类:一般是一个较为复杂的对象,也就是说创建对象...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java建造者模式在android上的实践
举报原因:
原因补充:

(最多只允许输入30个字)