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

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

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

该对话框将支持下面特性:
    1.    可从资源或者字符串直接指定对话框标题
    2.    可从资源、字符串和自定义布局来设置对话框内容
    3.    可设置按钮和相应的事件处理
 编写布局、样式和主题
该对话框使用一个定制的布局来输出内容,布局定义的id将用于访问标题 TextView,下面是定义文件:
01
<?xml version="1.0" encoding="utf-8"?>
02
 
03
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
04
    android:orientation="vertical"
05
    android:layout_width="fill_parent"
06
    android:minWidth="280dip"
07
    android:layout_height="wrap_content">
08
 
09
 
10
    <LinearLayout
11
        android:orientation="vertical"
12
        android:background="@drawable/header"
13
        android:layout_width="fill_parent"
14
        android:layout_height="wrap_content">
15
 
16
        <TextView
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
    </LinearLayout>
28
 
29
    <LinearLayout
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
        <TextView
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
    </LinearLayout>
46
 
47
    <LinearLayout
48
        android:orientation="horizontal"
49
        android:background="@drawable/footer"
50
 
51
        android:layout_width="fill_parent"
52
        android:layout_height="wrap_content">
53
 
54
        <Button
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
        <Button
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
    </LinearLayout>
74
 
75
</LinearLayout>

根节点 LinearLayout 的宽度设置为 fill_parent 而最小的宽度是 280dip ,因此对话框的宽度将始终为屏幕宽度的 87.5%
自定义的主题用于声明对话框是浮动的,而且使用自定义的背景和标题视图:
01
<?xml version="1.0" encoding="utf-8"?>
02
<resources>
03
 
04
    <style name="Dialog" parent="android:style/Theme.Dialog">
05
        <item name="android:windowBackground">@null</item>
06
 
07
        <item name="android:windowNoTitle">true</item>
08
        <item name="android:windowIsFloating">true</item>
09
    </style>
10
 
11
</resources>
接下来我们需要定义对话框的标题和消息的显示:
01
<?xml version="1.0" encoding="utf-8"?>
02
<resources>
03
 
04
    <style name="DialogText">
05
        <item name="android:textColor">#FF000000</item>
06
 
07
        <item name="android:textSize">12sp</item>
08
    </style>
09
 
10
    <style name="DialogText.Title">
11
        <item name="android:textSize">16sp</item>
12
 
13
        <item name="android:textStyle">bold</item>
14
    </style>
15
 
16
</resources>

编写对话框和 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 CustomDialog extends 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
}

完整的代码下载: SampleCustomDialog

原文地址:https://www.cnblogs.com/jiezzy/p/2949768.html