建造者模式打造随心所欲的Android对话框
来源:互联网 发布:java thread join 编辑:程序博客网 时间:2024/05/21 14:04
可能有人要说不就是自定义dialog吗,网上一搜案例demo多得是,而且也不难,没什么好讲的。确实百度一下自定义的dialog数不胜数。但是大多数文章都是单一的布局实现单一的样式。假如说项目中有多个不同布局的dialog,比如三种、五种甚至十种,当然我只说假如。如果你的项目只有一种样式的对话框。那么也没有必要再看再往下看了。
如上所述,碰到多种样式的对话框应该怎么办呢?总不能项目需要几种就去写几种自定义样式吧?很显然我们不会那样做!所以这就是写这篇文章的用意。接下来我们将通过建造者模式来自定义dialog,并对自定义的dialog做下简单封装,最后实现的需求是只需要写dialog的布局文件即可实现任意样式的对话框!有木有很心动?闲话不多扯了,开撸!
国际惯例,开撸前先看效果图。图中使用同一个自定义dialog实现了两种不同样式的对话框。
一、用建造者模式实现自定义Dialog
1.首先我们要做的是去自定义Dialog,创建CustomDialog并继承Dialog。
2.明确Dialog所需要的属性,宽度、高度、Dialog的布局所对应的View、点击外部是否取消dialog、以及Dialog的主题(Theme),其中主题(Theme)我们没有定义在CustomDialog内部,而是定义到了Builder中。因此需要在CustomDialog内定义如下成员变量:
// dialog高度 private int height; // dialog宽度 private int width; // 点击外部是否可以取消 private boolean cancelTouchOutside; // 对话框布局对应的View private View dialogView;
3.接下来我们在CustomDialog内部创建静态内部类Builder,根据Dialog布局计算dialog宽高,并给定默认的对话框布局样式custom_dialog2。如下图(页面布局代码不再贴出):
Builder代码如下:
public static final class Builder { private Context context; private int height, width; private boolean cancelTouchOutside; private View mDialogView; private int resStyle = -1; public Builder(Context context) { this.context = context; mDialogView = LayoutInflater.from(context).inflate(R.layout.custom_dialog2, null); // 计算dialog宽高 int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); mDialogView.measure(measureSpec, measureSpec); height = mDialogView.getMeasuredHeight(); width = mDialogView.getMeasuredWidth(); } /** * @param dialogView 关联dialog布局文件的View * @return */ public Builder setDialogLayout(View dialogView) { this.mDialogView = dialogView; return this; } public Builder setHeightPx(int val) { height = val; return this; } public Builder setWidthPx(int val) { width = val; return this; } public Builder setHeightDp(int val) { height = ScreenUtils.dp2px(context, val); return this; } public Builder setWidthDp(int val) { width = ScreenUtils.dp2px(context, val); return this; } /** * 设置主题 * * @param resStyle * @return */ public Builder setTheme(int resStyle) { this.resStyle = resStyle; return this; } /** * 设置点击dialog外部是否取消dialog * * @param val * @return */ public Builder cancelTouchOutside(boolean val) { cancelTouchOutside = val; return this; } /** * 给dialog中的view添加点击事件 * * @param viewResId 被点击view的id * @param listener * @return */ public Builder addViewOnclick(int viewResId, View.OnClickListener listener) { mDialogView.findViewById(viewResId).setOnClickListener(listener); return this; } /** * 确定键监听 * @param confirm * @param listener * @return */ public Builder addConfirmClickListener(String confirm, View.OnClickListener listener) { TextView tvConfirm = (TextView) mDialogView.findViewById(R.id.tv_confirm); tvConfirm.setText(confirm); tvConfirm.setOnClickListener(listener); return this; } /** * 取消键监听 * @param cancel * @param listener * @return */ public Builder addCancelClickListener(String cancel, View.OnClickListener listener) { TextView tvCancel = (TextView) mDialogView.findViewById(R.id.tv_cancel); tvCancel.setText(cancel); tvCancel.setOnClickListener(listener); return this; } /** * 设置内容 * @param content * @return */ public Builder setContent(String content) { TextView tvTitle = (TextView) mDialogView.findViewById(R.id.tv_dialog_content); tvTitle.setText(content); return this; } /** * 设置取消键颜色 * @param color 颜色 * @return */ public Builder setCancelColor(int color){ TextView tvCancel= (TextView) mDialogView.findViewById(R.id.tv_cancel); tvCancel.setTextColor(color); return this; } /** * 设置确定键颜色 * @param color 颜色 * @return */ public Builder setConfirmColor(int color){ TextView tvCancel= (TextView) mDialogView.findViewById(R.id.tv_confirm); tvCancel.setTextColor(color); return this; } /** * 显示一个按钮的弹窗 * @return */ public Builder showOneButton() { mDialogView.findViewById(R.id.tv_cancel).setVisibility(View.GONE); mDialogView.findViewById(R.id.view_dialog).setVisibility(View.GONE); return this; } public CustomDialog build() { if (resStyle != -1) { return new CustomDialog(this, resStyle); } else { return new CustomDialog(this); } } }
5.上面代码在build()方法中实例化了CustomDialog,因此我们不要忘了CustomDialog中的构造方法。在构造方法中获取Builder中的属性。构造方法有两个,如下:
private CustomDialog(Builder builder) { super(builder.context); height = builder.height; width = builder.width; cancelTouchOutside = builder.cancelTouchOutside; dialogView = builder.mDialogView; } private CustomDialog(Builder builder, int theme) { super(builder.context, theme); height = builder.height; width = builder.width; cancelTouchOutside = builder.cancelTouchOutside; dialogView = builder.mDialogView; }
6.最后还要在onCreate()中为dialog设置布局和一些其他属性。代码如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(dialogView); // 设置Touch的时候是否取消Dialog setCanceledOnTouchOutside(cancelTouchOutside); Window window = getWindow(); WindowManager.LayoutParams params = window.getAttributes(); params.gravity = Gravity.CENTER; params.height = height; params.width = width; window.setAttributes(params); }
这样自定义的Dialog就完成了。
二、对自定义的dialog简单封装。
完成自定义dialog之后接下来我们在项目的BaseActivity中对自定义的dialog做下封装。由于在构建DIalog的建造者时已经事先给定了默认布局,因此先对默认布局做下封装。
1.在BaseActivity中封装只有一个Button的对话框,并指定半透明背景样式,代码如下:
/** * @param content 内容 * @param confirm 按钮文字 * @param confirmListener 按钮监听 */ public void showOneButtonDialog(String content, String confirm, View.OnClickListener confirmListener) { dialog = new CustomDialog.Builder(this) .setTheme(R.style.CustomDialog1) .setContent(content) .addConfirmClickListener(confirm, confirmListener) .showOneButton() .build(); dialog.show(); }
2.封装两个按钮的dialog,指定半透明背景。代码如下:
/** * @param content 内容 * @param confirm 确定键文字 * @param cancel 取消键文字 * @param confirmListener 确定键监听 * @param cancelListener 取消键监听 */ public void showTwoButtonDialog(String content, String confirm, String cancel, View.OnClickListener confirmListener, View.OnClickListener cancelListener) { dialog = new CustomDialog.Builder(this) .setTheme(R.style.CustomDialog1) .setContent(content) .addConfirmClickListener(confirm, confirmListener) .addCancelClickListener(cancel, cancelListener) .build(); dialog.show(); }
3.封装两个按钮切能改变按钮字体颜色的对话框,背景指定全透明,代码如下:
/** * @param content 内容 * @param confirm 确定键文字 * @param cancel 取消键文字 * @param confirmColor 确定键颜色 * @param cancelColor 取消键颜色 * @param confirmListener 确定键监听 * @param cancelListener 取消键监听 */ public void showTwoButtonDialog(String content, String confirm, String cancel, @ColorInt int confirmColor, @ColorInt int cancelColor, View.OnClickListener confirmListener, View.OnClickListener cancelListener) { dialog = new CustomDialog.Builder(this) .setTheme(R.style.CustomDialog2) .setContent(content) .setConfirmColor(confirmColor) .setCancelColor(cancelColor) .addConfirmClickListener(confirm, confirmListener) .addCancelClickListener(cancel, cancelListener) .build(); dialog.show(); }
4.封装自定义样式的对话框,需要自行定义对话框布局文件。代码如下:
/** * create custom dialog * 可以定制任意的dialog样式 * * @param dialogLayoutRes dialog布局资源文件 * @param cancelTouchOutside 点击外部是否可以取消 * @return */ public View createCustomDialog(@LayoutRes int dialogLayoutRes, boolean cancelTouchOutside) { dialogView = LayoutInflater.from(this).inflate(dialogLayoutRes, null); // 计算dialog宽高 int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); dialogView.measure(measureSpec, measureSpec); int height = dialogView.getMeasuredHeight(); int width = dialogView.getMeasuredWidth(); dialog = new CustomDialog.Builder(this) .setTheme(R.style.CustomDialog1) .setHeightPx(height) .setWidthPx(width) .cancelTouchOutside(cancelTouchOutside) .setDialogLayout(dialogView).build(); dialog.show(); return dialogView; }
自定义样式的dialog由于没有给定点击事件,因此需要在Activity中添加dismiss dialog的方法,可以在子Activity中自定义点击事件的时候调用,如下:
/** * 隐藏dialog */ public void dismissDialog() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } }
三、在子Activity中根据需求显示不同的对话框。
MainActivity继承BaseActivity,并在MainActivity中调用BaseActivity中的不同对话框的方法显示对话框。代码如下:
// 显示一个按钮的对话框 private void showOneButton(){ showOneButtonDialog("一个Button的Dialog", "确定", new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }); } // 显示两个按钮的对话框 private void showTwoButton(){ showTwoButtonDialog("两个Button的Dialog", "确定", "取消", new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }, new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }); } // 显示两个按钮且可以改变按钮颜色且背景全透明的对话框 public void showTowButtonWithColor() { showTwoButtonDialog("改变Button颜色的Dialog\n背景全透明", "确定", "取消", Color.parseColor("#ff0000"), Color.parseColor("#00ff00"), new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }, new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }); } // 显示自定义样式的对话框 private void showCustomDialog() { mDialogView1 = createCustomDialog(R.layout.custom_dialog1, false); // 为自定义的dialog设置内容、添加点击事件 TextView viewById1 = (TextView) mDialogView1.findViewById(R.id.tv_dialog_content); viewById1.setText("自定义样式的Dialog"); mDialogView1.findViewById(R.id.btn_dialog).setOnClickListener(this); }
上面代码自定义对话框createCustomDialog()方法的返回值是自定义布局文件对应的View,因此可以通过该View获取到布局中的所有子View,然后为其设置内容或者监听事件。
项目链接
- 建造者模式打造随心所欲的Android对话框
- Android---自定义对话框、随心所欲
- Java建造者模式,Android建造者模式的AlertDialog
- Android的设计模式-建造者模式
- Android建造者模式
- 设计模式:Android AlertDialog的builder(建造者模式)
- Android 建造者(Builder)模式
- Android建造者模式笔记
- android 建造者设计模式
- Android打造万能的对话框Dialog(一)
- Android打造万能的对话框Dialog(二)
- Android打造万能的对话框Dialog(三)
- android设计模式之建造者模式
- Android中的设计模式--建造者模式
- Android设计模式应用---建造者模式
- Android设计模式-建造者模式
- Android中的设计模式--建造者模式
- Android设计模式之建造者模式
- JZOJsenior1396.2017.04.08【NOIP提高组】模拟赛B组 T2包裹快递
- Java中UIManager的几种外观
- C#学习笔记1——程序集
- ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: NO)
- 线程安全与可重入函数的区别
- 建造者模式打造随心所欲的Android对话框
- javac 错误: 找不到符号
- Java垃圾回收机制
- Ajax中
- Platform总线按键驱动分析(精华版)
- 深入理解java垃圾回收机制
- Java sdut acm 2397 分类游戏
- javascript hello world
- 我想要参加蓝桥杯——该怎么办呢