Plain's Blog

休想打败我的生活🔥

【安卓基础】构建一个通用的对话框(Dialog)

Plain's Avatar 2019-08-15 安卓笔记

  1. 1. 思路
  2. 2. 流程
  3. 3. 使用
  4. 4. 总结

对话框Dialog在开发中用到的挺多的,Android也为我们提供了AlertDialog帮助我们快速构建一个对话框,用以来也挺方便的。但大多数情况,我们的UI界面还得按照美工的设计来走,此时就不得不自定义对话框了,下面我将分享一下一种通用的构造对话框的方法,基本上大多数的对话框需求都能完成✅

思路

在平时的需求中,对话框的样子是最频繁变化的,所以我们可以将对话框的UI单拿出来,在外部设置布局。再就是对话框的作用,一般就是只展示文字或者有几个按钮再或者有个输入框与用户进行交互,所以我们可以把这些操作,整理成不同的方法,进行调用。再就是对话框的大小,这个我们可以在构建对话框的时候手动设置,来进行不同分辨率的适配。

流程

  • 统一对话框的样式
1
2
3
4
5
<style name="UserDialogStyle" parent="android:style/Theme.Dialog">
<item name="android:background">@android:color/transparent</item> //背景透明
<item name="android:windowBackground">@android:color/transparent</item> //窗口背景透明
<item name="android:windowNoTitle">true</item> //无标题
</style>
  • 自定义对话框(采用构建者模式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
public class UserDialog extends Dialog {

private boolean cancelTouchOut;
private boolean cancelable;
private boolean dimEnabled;
private View view;
private int height, width;
private long time;

private UserDialog(@NonNull Builder builder) {
this(builder, -1);
}

private UserDialog(@NonNull Builder builder, int resStyle) {
super(builder.context, resStyle);
cancelTouchOut = builder.cancelTouchOut;
cancelable = builder.cancelable;
dimEnabled = builder.dimEnabled;
view = builder.view;
height = builder.height;
width = builder.width;
time = builder.time;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(view);
setCanceledOnTouchOutside(cancelTouchOut);
setCancelable(cancelable);
//调整窗口大小
Window win = getWindow();
WindowManager.LayoutParams lp = win != null ? win.getAttributes() : null;
if (lp != null) {
lp.gravity = Gravity.CENTER;
}
if (lp != null) {
lp.height = height;
}
if (lp != null) {
lp.width = width;
}
if (win != null) {
win.setAttributes(lp);
}

if (lp != null) {
if (!dimEnabled) {
lp.dimAmount = 0f; //背景是否变暗
}
}

if (time > 0) {
new Thread(() -> {
try {
Thread.sleep(time);
dismiss();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}

}

public <T extends View> T findUserDialogViewById(@IdRes int id) {
return view.findViewById(id);
}

/**
* 外部设置View的隐藏显示
*
* @param viewRes View Id
* @param type Visibility
*/
public void setBtnVisibility(@IdRes int viewRes, int type) {
Button button = view.findViewById(viewRes);
button.setVisibility(type);
}

/**
* 外部设置输入框自动弹出键盘(500ms后)
*
* @param id EditText Id
*/
public void setEditTextShowInput(@IdRes int id) {
EditText editText = view.findViewById(id);
editText.setText("");
editText.postDelayed(() -> {
editText.requestFocus();
Utils.showDialogSoftInput(editText);
}, 500);
}

public static final class Builder {
private Context context;
private View view;
private boolean cancelTouchOut;
private boolean cancelable;
private boolean dimEnabled;
private int resStyle = -1;
private int height, width;
private long time = 0;

/**
* 构建者初始化
* @param context 上下文
* @param resStyle Dialog Style
*/
public Builder(Context context, int resStyle) {
this.context = context;
this.resStyle = resStyle;
}

/**
* Dialog所需View
* @param resView 布局
* @return Builder
*/
public Builder view(@LayoutRes int resView) {
view = LayoutInflater.from(context).inflate(resView, null);
return this;
}

/**
* 是否允许点击Dialog外关闭
* @param val true 允许 false 不允许
* @return Builder
*/
public Builder cancelTouchOut(boolean val) {
cancelTouchOut = val;
return this;
}

/**
* 是否允许点击返回键关闭
* @param val true 允许 false 不允许
* @return Builder
*/
public Builder cancelable(boolean val) {
cancelable = val;
return this;
}

/**
* 是否允许背景变暗
* @param val true 允许 false 不允许
* @return Builder
*/
public Builder setDimEnabled(boolean val) {
dimEnabled = val;
return this;
}

/**
* 为Button设置Text
* @param viewRes Button Id
* @param text 文本
* @return Builder
*/
public Builder addBtnText(@IdRes int viewRes, String text) {
Button button = view.findViewById(viewRes);
button.setText(text);
return this;
}

/**
* 为TextView设置Text
* @param viewRes TextView Id
* @param text 文本
* @return Builder
*/
public Builder addText(@IdRes int viewRes, String text) {
TextView textView = view.findViewById(viewRes);
textView.setText(text);
return this;
}

/**
* 为某个View设置点击事件监听
* @param viewRes View Id
* @param listener 点击事件
* @return Builder
*/
public Builder addViewOnclick(int viewRes, View.OnClickListener listener) {
view.findViewById(viewRes).setOnClickListener(listener);
return this;
}

/**
* 指定Dialog的宽度(P:与布局的宽度设置一致,效果最佳)
* @param dimenRes Width Dimen
* @return Builder
*/
public Builder widthDimenRes(int dimenRes) {
width = context.getResources().getDimensionPixelOffset(dimenRes);
return this;
}

/**
* 指定Dialog的高度(P:与布局的高度设置一致,效果最佳)
* @param dimenRes Height Dimen
* @return Builder
*/
public Builder heightDimenRes(int dimenRes) {
height = context.getResources().getDimensionPixelOffset(dimenRes);
return this;
}

/**
* 设置自动关闭Dialog(指定时间)
* @param t ms后消失
* @return Builder
*/
public Builder setTimeOut(long t) {
time = t;
return this;
}

/**
* 初始化时设置某个控件的隐藏
* @param viewRes View Id
* @param type Visibility
* @return Builder
*/
public Builder setViewVisibility(int viewRes, int type) {
View View = view.findViewById(viewRes);
View.setVisibility(type);
return this;
}

/**
* 构建结束,实例化UserDialog
* @return UserDialog
*/
public UserDialog build() {
if (resStyle != -1) {
return new UserDialog(this, resStyle);
} else {
return new UserDialog(this);
}
}
}
}

Builder中列举了我常用的几种对View的操作,大家可以根据自己的需求添加

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
UserDialog dialog = new UserDialog.Builder(mContext, R.style.UserDialogStyle)
.view(R.layout.layout_hint_dialog)
.cancelTouchOut(false)
.cancelable(false)
.setDimEnabled(true)
.addText(R.id.tv_content, "")
.addViewOnclick(R.id.btn_sure, v -> {
//具体操作
}
})
.widthDimenRes(R.dimen.size300)
.heightDimenRes(R.dimen.size180)
.build();
dialog.show();

总结

通过上面的操作,我们完成了一个通用的对话框构建器,只需指定需要的布局文件,然后根据需求设置不同的属性,就可以了。

本文作者 : Plain
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接 : https://plain-dev.com/general-dialog/

本文最后更新于 天前,文中所描述的信息可能已发生改变