打造BaseDialog
看这文章之前请移步红橙Darren大佬的Builder设计模式 - 构建整个应用的万能Dialog 。本篇文章参考红橙Darren,如有侵权,联系即删。
最近空闲的时候在学习红橙Darren大佬的自定义View。奈何工作中Dialog 的需求很多、刚好又看到参考这篇文章,于是跟着大佬敲了一遍。直接看代码吧。
- 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;
}
}
}
- 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);
}
}
}
- 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;
}
}
- 使用教程
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);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库