自定义 Android 对话框 (AlertDialog) 的样式



Android 提供了 AlertDialog 类可通过其内部类 Builder 轻松创建对话框窗口,但是没法对这个对话框窗口进行定制,为了修改 AlertDialog 窗口显示的外观,解决的办法就是创建一个指定的 AlertDialog 和 AlertDialog.Builder 类。

Android default Dialog

定义外观

我们希望将上面默认的对话框外观修改为如下图所示的新对话框风格:

Custom Android Dialog

该对话框将支持下面特性:

  1. 可从资源或者字符串直接指定对话框标题
  2. 可从资源、字符串和自定义布局来设置对话框内容
  3. 可设置按钮和相应的事件处理

 编写布局、样式和主题

该对话框使用一个定制的布局来输出内容,布局定义的id将用于访问标题 TextView,下面是定义文件:

?
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
<? xml version = "1.0" encoding = "utf-8" ?>
 
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     android:orientation = "vertical"
     android:layout_width = "fill_parent"
     android:minWidth = "280dip"
     android:layout_height = "wrap_content" >
 
  
     < LinearLayout
         android:orientation = "vertical"
         android:background = "@drawable/header"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content" >
  
         < TextView
             style = "@style/DialogText.Title"
 
             android:id = "@+id/title"
             android:paddingRight = "8dip"
             android:paddingLeft = "8dip"
             android:background = "@drawable/title"
             android:layout_width = "wrap_content"
 
             android:layout_height = "wrap_content" />
  
     </ LinearLayout >
  
     < LinearLayout
         android:id = "@+id/content"
         android:orientation = "vertical"
         android:background = "@drawable/center"
 
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content" >
  
         < TextView
             style = "@style/DialogText"
             android:id = "@+id/message"
             android:padding = "5dip"
 
             android:layout_width = "fill_parent"
             android:layout_height = "wrap_content" />
  
     </ LinearLayout >
  
     < LinearLayout
         android:orientation = "horizontal"
         android:background = "@drawable/footer"
 
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content" >
  
         < Button
             android:id = "@+id/positiveButton"
             android:layout_marginTop = "3dip"
             android:layout_width = "0dip"
 
             android:layout_weight = "1"
             android:layout_height = "wrap_content"
             android:singleLine = "true" />
  
         < Button
             android:id = "@+id/negativeButton"
 
             android:layout_marginTop = "3dip"
             android:layout_width = "0dip"
             android:layout_weight = "1"
             android:layout_height = "wrap_content"
             android:singleLine = "true" />
 
  
     </ LinearLayout >
  
</ LinearLayout >

根节点 LinearLayout 的宽度设置为 fill_parent 而最小的宽度是 280dip ,因此对话框的宽度将始终为屏幕宽度的 87.5%

自定义的主题用于声明对话框是浮动的,而且使用自定义的背景和标题视图:

?
1
2
3
4
5
6
7
8
9
10
11
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
  
     < style name = "Dialog" parent = "android:style/Theme.Dialog" >
         < item name = "android:windowBackground" >@null</ item >
 
         < item name = "android:windowNoTitle" >true</ item >
         < item name = "android:windowIsFloating" >true</ item >
     </ style >
  
</ resources >

接下来我们需要定义对话框的标题和消息的显示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
  
     < style name = "DialogText" >
         < item name = "android:textColor" >#FF000000</ item >
 
         < item name = "android:textSize" >12sp</ item >
     </ style >
  
     < style name = "DialogText.Title" >
         < item name = "android:textSize" >16sp</ item >
 
         < item name = "android:textStyle" >bold</ item >
     </ style >
  
</ resources >

编写对话框和 Builder 类

最好我们要提供跟 AletDialog.Builder 类一样的方法:

?
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
package net.androgames.blog.sample.customdialog.dialog;
  
import net.androgames.blog.sample.customdialog.R;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
  
/**
  *
  * Create custom Dialog windows for your application
  * Custom dialogs rely on custom layouts wich allow you to
  * create and use your own look & feel.
  *
  * Under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
  *
  * @author antoine vianey
  *
  */
public class CustomDialog extends Dialog {
  
     public CustomDialog(Context context, int theme) {
         super (context, theme);
     }
  
     public CustomDialog(Context context) {
         super (context);
     }
  
     /**
      * Helper class for creating a custom dialog
      */
     public static class Builder {
  
         private Context context;
         private String title;
         private String message;
         private String positiveButtonText;
         private String negativeButtonText;
         private View contentView;
  
         private DialogInterface.OnClickListener
                         positiveButtonClickListener,
                         negativeButtonClickListener;
  
         public Builder(Context context) {
             this .context = context;
         }
  
         /**
          * Set the Dialog message from String
          * @param title
          * @return
          */
         public Builder setMessage(String message) {
             this .message = message;
             return this ;
         }
  
         /**
          * Set the Dialog message from resource
          * @param title
          * @return
          */
         public Builder setMessage( int message) {
             this .message = (String) context.getText(message);
             return this ;
         }
  
         /**
          * Set the Dialog title from resource
          * @param title
          * @return
          */
         public Builder setTitle( int title) {
             this .title = (String) context.getText(title);
             return this ;
         }
  
         /**
          * Set the Dialog title from String
          * @param title
          * @return
          */
         public Builder setTitle(String title) {
             this .title = title;
             return this ;
         }
  
         /**
          * Set a custom content view for the Dialog.
          * If a message is set, the contentView is not
          * added to the Dialog...
          * @param v
          * @return
          */
         public Builder setContentView(View v) {
             this .contentView = v;
             return this ;
         }
  
         /**
          * Set the positive button resource and it's listener
          * @param positiveButtonText
          * @param listener
          * @return
          */
         public Builder setPositiveButton( int positiveButtonText,
                 DialogInterface.OnClickListener listener) {
             this .positiveButtonText = (String) context
                     .getText(positiveButtonText);
             this .positiveButtonClickListener = listener;
             return this ;
         }
  
         /**
          * Set the positive button text and it's listener
          * @param positiveButtonText
          * @param listener
          * @return
          */
         public Builder setPositiveButton(String positiveButtonText,
                 DialogInterface.OnClickListener listener) {
             this .positiveButtonText = positiveButtonText;
             this .positiveButtonClickListener = listener;
             return this ;
         }
  
         /**
          * Set the negative button resource and it's listener
          * @param negativeButtonText
          * @param listener
          * @return
          */
         public Builder setNegativeButton( int negativeButtonText,
                 DialogInterface.OnClickListener listener) {
             this .negativeButtonText = (String) context
                     .getText(negativeButtonText);
             this .negativeButtonClickListener = listener;
             return this ;
         }
  
         /**
          * Set the negative button text and it's listener
          * @param negativeButtonText
          * @param listener
          * @return
          */
         public Builder setNegativeButton(String negativeButtonText,
                 DialogInterface.OnClickListener listener) {
             this .negativeButtonText = negativeButtonText;
             this .negativeButtonClickListener = listener;
             return this ;
         }
  
         /**
          * Create the custom dialog
          */
         public CustomDialog create() {
             LayoutInflater inflater = (LayoutInflater) context
                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             // instantiate the dialog with the custom Theme
             final CustomDialog dialog = new CustomDialog(context,
                     R.style.Dialog);
             View layout = inflater.inflate(R.layout.dialog, null );
             dialog.addContentView(layout, new LayoutParams(
                     LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
             // set the dialog title
             ((TextView) layout.findViewById(R.id.title)).setText(title);
             // set the confirm button
             if (positiveButtonText != null ) {
                 ((Button) layout.findViewById(R.id.positiveButton))
                         .setText(positiveButtonText);
                 if (positiveButtonClickListener != null ) {
                     ((Button) layout.findViewById(R.id.positiveButton))
                             .setOnClickListener( new View.OnClickListener() {
                                 public void onClick(View v) {
                                     positiveButtonClickListener.onClick(
                                             dialog,
                                             DialogInterface.BUTTON_POSITIVE);
                                 }
                             });
                 }
             } else {
                 // if no confirm button just set the visibility to GONE
                 layout.findViewById(R.id.positiveButton).setVisibility(
                         View.GONE);
             }
             // set the cancel button
             if (negativeButtonText != null ) {
                 ((Button) layout.findViewById(R.id.negativeButton))
                         .setText(negativeButtonText);
                 if (negativeButtonClickListener != null ) {
                     ((Button) layout.findViewById(R.id.negativeButton))
                             .setOnClickListener( new View.OnClickListener() {
                                 public void onClick(View v) {
                                     positiveButtonClickListener.onClick(
                                             dialog,
                                             DialogInterface.BUTTON_NEGATIVE);
                                 }
                             });
                 }
             } else {
                 // if no confirm button just set the visibility to GONE
                 layout.findViewById(R.id.negativeButton).setVisibility(
                         View.GONE);
             }
             // set the content message
             if (message != null ) {
                 ((TextView) layout.findViewById(
                         R.id.message)).setText(message);
             } else if (contentView != null ) {
                 // if no message set
                 // add the contentView to the dialog body
                 ((LinearLayout) layout.findViewById(R.id.content))
                         .removeAllViews();
                 ((LinearLayout) layout.findViewById(R.id.content))
                         .addView(contentView,
                                 new LayoutParams(
                                         LayoutParams.WRAP_CONTENT,
                                         LayoutParams.WRAP_CONTENT));
             }
             dialog.setContentView(layout);
             return dialog;
         }
  
     }
  
}

使用自定义的 Builder

使用方法很简单:

?
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
/**
  * Build the desired Dialog
  * CUSTOM or DEFAULT
  */
@Override
public Dialog onCreateDialog( int dialogId) {
     Dialog dialog = null ;
     switch (dialogId) {
         case CUSTOM_DIALOG :
             CustomDialog.Builder customBuilder = new
                 CustomDialog.Builder(CustomDialogActivity. this );
             customBuilder.setTitle( "Custom title" )
                 .setMessage( "Custom body" )
                 .setNegativeButton( "Cancel" ,
                         new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
                         CustomDialogActivity. this
                         .dismissDialog(CUSTOM_DIALOG);
                     }
                 })
                 .setPositiveButton( "Confirm" ,
                         new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
                         dialog.dismiss();
                     }
                 });
             dialog = customBuilder.create();
             break ;
         case DEFAULT_DIALOG :
             AlertDialog.Builder alertBuilder = new
                 AlertDialog.Builder(CustomDialogActivity. this );
             alertBuilder.setTitle( "Default title" )
                 .setMessage( "Default body" )
                 .setNegativeButton( "Cancel" ,
                         new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
                         dialog.dismiss();
                     }
                 })
                 .setPositiveButton( "Confirm" ,
                         new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
                         CustomDialogActivity. this
                         .dismissDialog(DEFAULT_DIALOG);
                     }
                 });
             dialog = alertBuilder.create();
             break ;
     }
     return dialog;
}

完整的代码下载: SampleCustomDialog

Enjoy !

http://blog.androgames.net/10/custom-android-dialog/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值