Android 提供了 AlertDialog 类可通过其内部类 Builder 轻松创建对话框窗口,但是没法对这个对话框窗口进行定制,为了修改 AlertDialog 窗口显示的外观,解决的办法就是创建一个指定的 AlertDialog 和 AlertDialog.Builder 类。
定义外观
我们希望将上面默认的对话框外观修改为如下图所示的新对话框风格:
该对话框将支持下面特性:
可从资源或者字符串直接指定对话框标题
可从资源、字符串和自定义布局来设置对话框内容
可设置按钮和相应的事件处理
编写布局、样式和主题
该对话框使用一个定制的布局来输出内容,布局定义的id将用于访问标题 TextView,下面是定义文件:
01
02
03
04
android:orientation="vertical"
05
android:layout_width="fill_parent"
06
android:minWidth="280dip"
07
android:layout_height="wrap_content">
08
09
10
11
android:orientation="vertical"
12
android:background="@drawable/header"
13
android:layout_width="fill_parent"
14
android:layout_height="wrap_content">
15
16
17
style="@style/DialogText.Title"
18
19
android:id="@+id/title"
20
android:paddingRight="8dip"
21
android:paddingLeft="8dip"
22
android:background="@drawable/title"
23
android:layout_width="wrap_content"
24
25
android:layout_height="wrap_content"/>
26
27
28
29
30
android:id="@+id/content"
31
android:orientation="vertical"
32
android:background="@drawable/center"
33
34
android:layout_width="fill_parent"
35
android:layout_height="wrap_content">
36
37
38
style="@style/DialogText"
39
android:id="@+id/message"
40
android:padding="5dip"
41
42
android:layout_width="fill_parent"
43
android:layout_height="wrap_content"/>
44
45
46
47
48
android:orientation="horizontal"
49
android:background="@drawable/footer"
50
51
android:layout_width="fill_parent"
52
android:layout_height="wrap_content">
53
54
55
android:id="@+id/positiveButton"
56
android:layout_marginTop="3dip"
57
android:layout_width="0dip"
58
59
android:layout_weight="1"
60
android:layout_height="wrap_content"
61
android:singleLine="true"/>
62
63
64
android:id="@+id/negativeButton"
65
66
android:layout_marginTop="3dip"
67
android:layout_width="0dip"
68
android:layout_weight="1"
69
android:layout_height="wrap_content"
70
android:singleLine="true"/>
71
72
73
74
75
根节点 LinearLayout 的宽度设置为 fill_parent 而最小的宽度是 280dip ,因此对话框的宽度将始终为屏幕宽度的 87.5%
自定义的主题用于声明对话框是浮动的,而且使用自定义的背景和标题视图:
01
02
03
04
05
@null
06
07
true
08
true
09
10
11
接下来我们需要定义对话框的标题和消息的显示:
01
02
03
04
05
#FF000000
06
07
12sp
08
09
10
11
16sp
12
13
bold
14
15
16
编写对话框和 Builder 类
最好我们要提供跟 AletDialog.Builder 类一样的方法:
001
package net.androgames.blog.sample.customdialog.dialog;
002
003
import net.androgames.blog.sample.customdialog.R;
004
import android.app.Dialog;
005
import android.content.Context;
006
import android.content.DialogInterface;
007
import android.view.LayoutInflater;
008
import android.view.View;
009
import android.view.ViewGroup.LayoutParams;
010
import android.widget.Button;
011
import android.widget.LinearLayout;
012
import android.widget.TextView;
013
014
/**
015
*
016
* Create custom Dialog windows for your application
017
* Custom dialogs rely on custom layouts wich allow you to
018
* create and use your own look & feel.
019
*
020
* Under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
021
*
022
* @author antoine vianey
023
*
024
*/
025
public class CustomDialogextends Dialog {
026
027
public CustomDialog(Context context,int theme) {
028
super(context, theme);
029
}
030
031
public CustomDialog(Context context) {
032
super(context);
033
}
034
035
/**
036
* Helper class for creating a custom dialog
037
*/
038
public static class Builder {
039
040
private Context context;
041
private String title;
042
private String message;
043
private String positiveButtonText;
044
private String negativeButtonText;
045
private View contentView;
046
047
private DialogInterface.OnClickListener
048
positiveButtonClickListener,
049
negativeButtonClickListener;
050
051
public Builder(Context context) {
052
this.context = context;
053
}
054
055
/**
056
* Set the Dialog message from String
057
* @param title
058
* @return
059
*/
060
public Builder setMessage(String message) {
061
this.message = message;
062
return this;
063
}
064
065
/**
066
* Set the Dialog message from resource
067
* @param title
068
* @return
069
*/
070
public Builder setMessage(int message) {
071
this.message = (String) context.getText(message);
072
return this;
073
}
074
075
/**
076
* Set the Dialog title from resource
077
* @param title
078
* @return
079
*/
080
public Builder setTitle(int title) {
081
this.title = (String) context.getText(title);
082
return this;
083
}
084
085
/**
086
* Set the Dialog title from String
087
* @param title
088
* @return
089
*/
090
public Builder setTitle(String title) {
091
this.title = title;
092
return this;
093
}
094
095
/**
096
* Set a custom content view for the Dialog.
097
* If a message is set, the contentView is not
098
* added to the Dialog...
099
* @param v
100
* @return
101
*/
102
public Builder setContentView(View v) {
103
this.contentView = v;
104
return this;
105
}
106
107
/**
108
* Set the positive button resource and it's listener
109
* @param positiveButtonText
110
* @param listener
111
* @return
112
*/
113
public Builder setPositiveButton(int positiveButtonText,
114
DialogInterface.OnClickListener listener) {
115
this.positiveButtonText = (String) context
116
.getText(positiveButtonText);
117
this.positiveButtonClickListener = listener;
118
return this;
119
}
120
121
/**
122
* Set the positive button text and it's listener
123
* @param positiveButtonText
124
* @param listener
125
* @return
126
*/
127
public Builder setPositiveButton(String positiveButtonText,
128
DialogInterface.OnClickListener listener) {
129
this.positiveButtonText = positiveButtonText;
130
this.positiveButtonClickListener = listener;
131
return this;
132
}
133
134
/**
135
* Set the negative button resource and it's listener
136
* @param negativeButtonText
137
* @param listener
138
* @return
139
*/
140
public Builder setNegativeButton(int negativeButtonText,
141
DialogInterface.OnClickListener listener) {
142
this.negativeButtonText = (String) context
143
.getText(negativeButtonText);
144
this.negativeButtonClickListener = listener;
145
return this;
146
}
147
148
/**
149
* Set the negative button text and it's listener
150
* @param negativeButtonText
151
* @param listener
152
* @return
153
*/
154
public Builder setNegativeButton(String negativeButtonText,
155
DialogInterface.OnClickListener listener) {
156
this.negativeButtonText = negativeButtonText;
157
this.negativeButtonClickListener = listener;
158
return this;
159
}
160
161
/**
162
* Create the custom dialog
163
*/
164
public CustomDialog create() {
165
LayoutInflater inflater = (LayoutInflater) context
166
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
167
// instantiate the dialog with the custom Theme
168
final CustomDialog dialog =new CustomDialog(context,
169
R.style.Dialog);
170
View layout = inflater.inflate(R.layout.dialog,null);
171
dialog.addContentView(layout,new LayoutParams(
172
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
173
// set the dialog title
174
((TextView) layout.findViewById(R.id.title)).setText(title);
175
// set the confirm button
176
if (positiveButtonText !=null) {
177
((Button) layout.findViewById(R.id.positiveButton))
178
.setText(positiveButtonText);
179
if (positiveButtonClickListener !=null) {
180
((Button) layout.findViewById(R.id.positiveButton))
181
.setOnClickListener(new View.OnClickListener() {
182
public void onClick(View v) {
183
positiveButtonClickListener.onClick(
184
dialog,
185
DialogInterface.BUTTON_POSITIVE);
186
}
187
});
188
}
189
}else {
190
// if no confirm button just set the visibility to GONE
191
layout.findViewById(R.id.positiveButton).setVisibility(
192
View.GONE);
193
}
194
// set the cancel button
195
if (negativeButtonText !=null) {
196
((Button) layout.findViewById(R.id.negativeButton))
197
.setText(negativeButtonText);
198
if (negativeButtonClickListener !=null) {
199
((Button) layout.findViewById(R.id.negativeButton))
200
.setOnClickListener(new View.OnClickListener() {
201
public void onClick(View v) {
202
positiveButtonClickListener.onClick(
203
dialog,
204
DialogInterface.BUTTON_NEGATIVE);
205
}
206
});
207
}
208
}else {
209
// if no confirm button just set the visibility to GONE
210
layout.findViewById(R.id.negativeButton).setVisibility(
211
View.GONE);
212
}
213
// set the content message
214
if (message !=null) {
215
((TextView) layout.findViewById(
216
R.id.message)).setText(message);
217
}else if (contentView !=null) {
218
// if no message set
219
// add the contentView to the dialog body
220
((LinearLayout) layout.findViewById(R.id.content))
221
.removeAllViews();
222
((LinearLayout) layout.findViewById(R.id.content))
223
.addView(contentView,
224
new LayoutParams(
225
LayoutParams.WRAP_CONTENT,
226
LayoutParams.WRAP_CONTENT));
227
}
228
dialog.setContentView(layout);
229
return dialog;
230
}
231
232
}
233
234
}
使用自定义的 Builder
使用方法很简单:
01
/**
02
* Build the desired Dialog
03
* CUSTOM or DEFAULT
04
*/
05
@Override
06
public Dialog onCreateDialog(int dialogId) {
07
Dialog dialog =null;
08
switch (dialogId) {
09
case CUSTOM_DIALOG :
10
CustomDialog.Builder customBuilder =new
11
CustomDialog.Builder(CustomDialogActivity.this);
12
customBuilder.setTitle("Custom title")
13
.setMessage("Custom body")
14
.setNegativeButton("Cancel",
15
new DialogInterface.OnClickListener() {
16
public void onClick(DialogInterface dialog,int which) {
17
CustomDialogActivity.this
18
.dismissDialog(CUSTOM_DIALOG);
19
}
20
})
21
.setPositiveButton("Confirm",
22
new DialogInterface.OnClickListener() {
23
public void onClick(DialogInterface dialog,int which) {
24
dialog.dismiss();
25
}
26
});
27
dialog = customBuilder.create();
28
break;
29
case DEFAULT_DIALOG :
30
AlertDialog.Builder alertBuilder =new
31
AlertDialog.Builder(CustomDialogActivity.this);
32
alertBuilder.setTitle("Default title")
33
.setMessage("Default body")
34
.setNegativeButton("Cancel",
35
new DialogInterface.OnClickListener() {
36
public void onClick(DialogInterface dialog,int which) {
37
dialog.dismiss();
38
}
39
})
40
.setPositiveButton("Confirm",
41
new DialogInterface.OnClickListener() {
42
public void onClick(DialogInterface dialog,int which) {
43
CustomDialogActivity.this
44
.dismissDialog(DEFAULT_DIALOG);
45
}
46
});
47
dialog = alertBuilder.create();
48
break;
49
}
50
return dialog;
51
}