打造BaseDialog

看这文章之前请移步红橙Darren大佬的Builder设计模式 - 构建整个应用的万能Dialog 。本篇文章参考红橙Darren,如有侵权,联系即删。

最近空闲的时候在学习红橙Darren大佬的自定义View。奈何工作中Dialog 的需求很多、刚好又看到参考这篇文章,于是跟着大佬敲了一遍。直接看代码吧。

  1. BaseDialog
public class BaseDialog extends Dialog {

    public DialogController mAlert;

    public BaseDialog(Context context, int themeResId) {
        super(context, themeResId);
        mAlert = new DialogController(this, getWindow());
    }

    public <T extends View> T getView(int viewId) {
        return mAlert.getView(viewId);
    }

    public void setOnClickListener(int viewId, View.OnClickListener listener) {
        mAlert.setOnClickListener(viewId, listener);
    }

    public static class Builder {

        private DialogController.AlertParams P;

        public Builder(Context context) {
            this(context, R.style.CustomDialogTheme);
        }

        public Builder(Context context, int themeResId) {
            P = new DialogController.AlertParams(themeResId, context);
            P.themeResId = themeResId;
            P.context = context;
        }

        public Builder setText(int viewId, CharSequence text) {
            P.textArray.put(viewId, text);
            return this;
        }

        public Builder setWidthAndHeight(int width, int height) {
            P.width = width;
            P.height = height;
            return this;
        }

        public Builder setWidth(int width) {
            P.width = width;
            return this;
        }

        public Builder setOnClickListener(int viewId, View.OnClickListener listener) {
            P.clickArray.put(viewId, listener);
            return this;
        }


        /**
         * Sets the dialog Absolute position base on the layoutParams.gravity
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setGravity(int gravity) {
            P.gravity = gravity;
            return this;
        }

        public Builder setXAndY(int x, int y) {
            P.x = x;
            P.y = y;
            return this;
        }

        public Builder setX(int x) {
            P.x = x;
            return this;
        }

        public Builder setContentView(int layoutId) {
            P.view = null;
            P.layoutId = layoutId;
            return this;
        }

        public Builder setContentView(View view) {
            P.layoutId = 0;
            P.view = view;
            return this;
        }

        /**
         * Sets whether the dialog is cancelable or not.  Default is true.
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setCancelable(boolean cancelable) {
            P.cancelable = cancelable;
            return this;
        }


        /**
         * Sets the callback that will be called if the dialog is canceled.
         * <p>
         * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than
         * being canceled or one of the supplied choices being selected.
         * If you are interested in listening for all cases where the dialog is dismissed
         * and not just when it is canceled, see
         * { setOnDismissListener(OnDismissListener) setOnDismissListener}.</p>
         *
         * @return This Builder object to allow for chaining of calls to set methods
         * @see #setCancelable(boolean)
         * setOnDismissListener(OnDismissListener)
         */
        public Builder setOnCancelListener(DialogInterface.OnCancelListener onCancelListener) {
            P.onCancelListener = onCancelListener;
            return this;
        }

        /**
         * Sets the callback that will be called when the dialog is dismissed for any reason.
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
            P.onDismissListener = onDismissListener;
            return this;
        }

        /**
         * Sets the callback that will be called if a key is dispatched to the dialog.
         *
         * @return This Builder object to allow for chaining of calls to set methods
         */
        public Builder setOnKeyListener(DialogInterface.OnKeyListener onKeyListener) {
            P.onKeyListener = onKeyListener;
            return this;
        }


        /**
         * Creates an { AlertDialog} with the arguments supplied to this
         * builder.
         * <p/>
         * Calling this method does not display the dialog. If no additional
         * processing is needed, {@link #show()} may be called instead to both
         * create and display the dialog.
         */
        public BaseDialog create() {
            // Context has already been wrapped with the appropriate theme.
            final BaseDialog dialog = new BaseDialog(P.context, P.themeResId);
            P.apply(dialog.mAlert);
            dialog.setCancelable(P.cancelable);
            if (P.cancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
            if (P.onCancelListener != null) {
                dialog.setOnCancelListener(P.onCancelListener);
            }
            if (P.onDismissListener != null) {
                dialog.setOnDismissListener(P.onDismissListener);
            }
            if (P.onKeyListener != null) {
                dialog.setOnKeyListener(P.onKeyListener);
            }
            return dialog;
        }

        /**
         * Creates an { AlertDialog} with the arguments supplied to this
         * builder and immediately displays the dialog.
         * <p/>
         * Calling this method is functionally identical to:
         * <pre>
         *     AlertDialog dialog = builder.create();
         *     dialog.show();
         * </pre>
         */
        public BaseDialog show() {
            final BaseDialog dialog = create();
            dialog.show();
            return dialog;
        }
    }
}
  1. DialogController
public class DialogController {  
  
    private DialogViewHelper mViewHelper;  
    private BaseDialog mDialog;  
    private Window mWindow;  
  
    public DialogController(BaseDialog dialog, Window window) {  
        mDialog = dialog;  
        mWindow = window;  
    }  
  
    /**  
     * 获取Dialog  
     *     * @return  
     */  
    public BaseDialog getDialog() {  
        return mDialog;  
    }  
  
    /**  
     * 获取window  
     *     * @return  
     */  
    public Window getWindow() {  
        return mWindow;  
    }  
  
    public DialogViewHelper getViewHelper() {  
        return mViewHelper;  
    }  
  
    /**  
     * 设置View的辅助  
     *  
     * @param viewHelper  
     */  
    public void setDialogViewHelper(DialogViewHelper viewHelper) {  
        this.mViewHelper = viewHelper;  
    }  
  
    /**  
     * 设置文本  
     *  
     * @param viewId  
     * @param text  
     */  
    public void setText(int viewId, CharSequence text) {  
        mViewHelper.setText(viewId, text);  
    }  
  
    /**  
     * 设置点击事件  
     *  
     * @param viewId  
     * @param listener  
     */  
    public void setOnClickListener(int viewId, View.OnClickListener listener) {  
        mViewHelper.setOnClickListener(viewId, listener);  
    }  
  
    /**  
     * 通过id获取View  
     *     * @param viewId  
     * @param <T>  
     * @return  
     */  
    public <T extends View> T getView(int viewId) {  
        return mViewHelper.getView(viewId);  
    }  
  
    public static class AlertParams {  
        public int themeResId;  
        public Context context;  
        public boolean cancelable = false;  
        public DialogInterface.OnCancelListener onCancelListener;  
        public DialogInterface.OnDismissListener onDismissListener;  
        public DialogInterface.OnKeyListener onKeyListener;  
        public View view;  
        public int layoutId;  
        public SparseArray<CharSequence> textArray = new SparseArray<>();  
        public SparseArray<View.OnClickListener> clickArray = new SparseArray<>();  
        public int width = ViewGroup.LayoutParams.WRAP_CONTENT;  
        public int height = ViewGroup.LayoutParams.WRAP_CONTENT;  
        public int x = 0;  
        public int y = 0;  
        public int gravity = Gravity.CENTER;  
  
        public AlertParams(int themeResId, Context context) {  
            this.themeResId = themeResId;  
            this.context = context;  
        }  
  
        public void apply(DialogController mAlert) {  
  
            DialogViewHelper viewHelper = null;  
  
            if (layoutId != 0) {  
                viewHelper = new DialogViewHelper(context, layoutId);  
            }  
  
            if (view != null) {  
                viewHelper = new DialogViewHelper();  
                viewHelper.setContentView(view);  
            }  
            mAlert.setDialogViewHelper(viewHelper);  
  
            if (viewHelper != null)  
                mAlert.getDialog().setContentView(viewHelper.getContentView());  
  
            //设置文本  
            int textArraySize = textArray.size();  
            for (int i = 0; i < textArraySize; i++) {  
                mAlert.setText(textArray.keyAt(i), textArray.valueAt(i));  
            }  
  
            //设置点击事件  
            int clickArraySize = clickArray.size();  
            for (int i = 0; i < clickArraySize; i++) {  
                mAlert.setOnClickListener(clickArray.keyAt(i), clickArray.valueAt(i));  
            }  
  
            //设置Dialog宽高、绝对位置、gravity  
            WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();  
            layoutParams.width = width;  
            layoutParams.height = height;  
            layoutParams.gravity = gravity;  
            layoutParams.y = y;  
            layoutParams.x = x;  
  
            mAlert.getDialog().getWindow().setAttributes(layoutParams);  
        }  
    }  
}
  1. DialogViewHelper
public class DialogViewHelper {  
  
    private View mContentView = null;  
  
    //缓存View 减少View findViewById  
    private SparseArray<WeakReference<View>> mViews;  //WeakReference防止霸气侧漏、内存泄漏.  
  
    public DialogViewHelper(Context context, int layoutId) {  
        this();  
        mContentView = LayoutInflater.from(context).inflate(layoutId, null);  
    }  
  
    public DialogViewHelper() {  
        if (mViews == null) {  
            mViews = new SparseArray<>();  
        }  
    }  
  
    public void setContentView(View view) {  
        mContentView = view;  
    }  
  
  
  
    public void setText(int viewId, CharSequence charSequence) {  
        TextView view = getView(viewId);  
        if (view != null) {  
            view.setText(charSequence);  
        }  
    }  
  
    public void setOnClickListener(int viewId, View.OnClickListener listener) {  
        View view = getView(viewId);  
        if (view != null) {  
            view.setOnClickListener(listener);  
        }  
    }  
  
    public <T extends View> T getView(int viewId) {  
        View view;  
        WeakReference<View> viewWeakReference = mViews.get(viewId);  
        if (viewWeakReference == null) {  
            view = mContentView.findViewById(viewId);  
            if (view != null) {  
                mViews.put(viewId, new WeakReference<>(view));  
            }  
        } else {  
            view = viewWeakReference.get();  
        }  
        return (T) view;  
    }  
  
    public View getContentView() {  
        return mContentView;  
    }  
}
  1. 使用教程
BaseDialog dialog= new BaseDialog.Builder(this).  
        setContentView(R.layout.layout_net_out_create).  
        setWidthAndHeight(896, 150).  //设置宽高、默认都是 WRAP_CONTENT
        setCancelable(true).         //是否点击外部可以取消                                              
        setXAndY(400, 500).    //相对位置 默认是0,0  
        setGravity(Gravity.TOP).   //默认是Gravity.CENTER  
        create();  
  
dialog.show();  
  
//设置点击事件  
dialog.setOnClickListener(R.id.dialog_finish_vote_cancel, new View.OnClickListener() {  
    @Override  
    public void onClick(View view) {  
        dialog.dismiss();  
    }  
});  
  
//可以拿到View 的实例  
final TextView textView=dialog.getView(R.id.dialog_finish_vote_cancel);

posted @ 2023-07-20 14:14  炸憨啪  阅读(48)  评论(0编辑  收藏  举报