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

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

Android default Dialog

定义外观

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

Custom Android Dialog

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

  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

Enjoy !

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

原文地址:https://www.cnblogs.com/chiuschen/p/3155999.html