服务电话:0531-81180830 | 24小时服务:13176691830
公司新闻

自定义AlertDialog的实现

今天就讲一下如何在Android中自定义 AlertDialog,请先看下面的效果图:


当点击“取消”或者“保存”按钮的时候,都会弹出对话框来通知用户,而这个对话框就是自定义的AlertDialog。

1)第一步:自定义布局,如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@drawable/shape_alert_dialog"  
  6.     android:minWidth="280dp"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <TextView  
  10.         android:id="@+id/tvAlertDialogTitle"  
  11.         android:textSize="20sp"  
  12.         android:textStyle="bold"  
  13.         android:layout_width="wrap_content"  
  14.         android:textColor="#FFFFFF"  
  15.         android:layout_height="50dp"  
  16.         android:layout_gravity="center"  
  17.         android:gravity="center" />  
  18.   
  19.     <View  
  20.         android:id="@+id/vTitleLine"  
  21.         android:layout_width="match_parent"  
  22.         android:layout_height="1dp"  
  23.         android:background="@drawable/line_divider" >  
  24.     </View>  
  25.   
  26.     <TextView  
  27.         android:id="@+id/tvAlertDialogMessage"  
  28.         android:layout_width="match_parent"  
  29.         android:textSize="16sp"  
  30.         android:layout_height="50dp"          
  31.         android:visibility="gone" />  
  32.   
  33.     <View  
  34.         android:id="@+id/vMessageLine"  
  35.         android:layout_width="match_parent"  
  36.         android:layout_height="1dp"  
  37.         android:background="@drawable/line_divider"  
  38.         android:visibility="gone" >  
  39.     </View>  
  40.   
  41.     <RelativeLayout  
  42.         android:id="@+id/rlAlertDialogButtons"  
  43.         android:layout_width="270dp"  
  44.         android:layout_marginBottom="10dp"  
  45.         android:layout_height="50dp"  
  46.         android:layout_gravity="center" >  
  47.   
  48.         <Button  
  49.             android:id="@+id/btnAlertDialogNegative"  
  50.             android:layout_width="120dp"  
  51.             android:layout_height="match_parent"  
  52.             android:layout_alignParentLeft="true"  
  53.             android:layout_alignParentTop="true"  
  54.             android:layout_margin="5dp"  
  55.             android:textColor="#FFFFFF"  
  56.             android:background="@drawable/shape_alert_button"  
  57.             android:gravity="center" />  
  58.   
  59.         <Button  
  60.             android:id="@+id/btnAlertDialogPositive"  
  61.             android:layout_width="120dp"  
  62.             android:layout_height="match_parent"  
  63.             android:layout_alignParentRight="true"  
  64.             android:layout_alignParentTop="true"  
  65.             android:layout_margin="5dp"  
  66.             android:textColor="#FFFFFF"  
  67.             android:background="@drawable/shape_alert_button"  
  68.             android:gravity="center" />  
  69.     </RelativeLayout>  
  70.   
  71. </LinearLayout>  

在上面的布局,定义了两个TextView,分别用来展示标题(Title)和信息(Message),还包括两条分隔线,最下面是两个按钮,至于具体的风格是怎么样的,就由各位发挥了。

2)第二步,我们要创建一个CustomAlertDialog类,继承Dialog类,为了延续Android原先的代码风格,我们可以模仿原来的AlertDialog类,创建builder类,具体代码如下:

2.1)首先是构造函数:

  1. public class CustomAlertDialog extends Dialog {  
  2.       
  3.   
  4.     public CustomAlertDialog(Context context) {  
  5.         super(context);  
  6.     }  
  7.   
  8.     public CustomAlertDialog(Context context, int themeId) {  
  9.         super(context, themeId);  
  10.     }  
在这里,定义了其中一个构造函数,它的第二个参数是一个themeID,这是因为要利用系统原先的Dialog的属性,所以会继承系统的Dialog主题,进行修改,在styles.xml中定义如下:

  1. <!-- Custom Alert Dialog -->  
  2. <style name="CustomAlertDialog" parent="android:style/Theme.Dialog">  
  3.     <item name="android:windowBackground">@android:color/transparent</item>  
  4.     <item name="android:windowNoTitle">true</item>  
  5.     <item name="android:windowIsFloating">true</item>  
  6. </style>  
在这个style中,

a)会将Dialog的windowBackground属性设置为透明,从而去掉系统原先默认对话框的背景,

b)将系统对话框的标题给去掉,

c)对话框的飘浮属性要设置为true,使得这个对话框可以浮在View上面。

2.2)创建Builder类,里面会依照AlertDialog类的方法,设置我们需要的方法,比如在上面的demo中,只需要”确定“跟”取消“按钮,"标题”跟“信息”这几项,所以我们就不需要去实现其他的方法了,具体代码如下:

  1. public static class Builder {  
  2.           
  3.         private Context mContext;  
  4.         private String mTitle, mMessage;  
  5.         private String mPositiveButtonText, mNegativeButtonText;  
  6.   
  7.         private OnClickListener mPositiveButtonClickListener,  
  8.                 mNegativeButtonClickListener;  
  9.   
  10.         public Builder(Context context) {  
  11.             mContext = context;  
  12.         }  
  13.   
  14.         public Builder setTitle(int resId) {  
  15.             mTitle = (String) mContext.getText(resId);  
  16.             return this;  
  17.         }  
  18.   
  19.         public Builder setTitle(String title) {  
  20.             mTitle = title;  
  21.             return this;  
  22.         }  
  23.   
  24.         public Builder setMessage(int resId) {  
  25.             mMessage = (String) mContext.getText(resId);  
  26.             return this;  
  27.         }  
  28.   
  29.         public Builder setMessage(String message) {  
  30.             mMessage = message;  
  31.             return this;  
  32.         }  
  33.   
  34.         public Builder setPositiveButton(int positiveButtonTextId,  
  35.                 OnClickListener listener) {  
  36.             mPositiveButtonText = (String) mContext  
  37.                     .getText(positiveButtonTextId);  
  38.             mPositiveButtonClickListener = listener;  
  39.             return this;  
  40.         }  
  41.   
  42.         public Builder setPositiveButton(String positiveButtonText,  
  43.                 OnClickListener listener) {  
  44.             mPositiveButtonText = positiveButtonText;  
  45.             mPositiveButtonClickListener = listener;  
  46.             return this;  
  47.         }  
  48.   
  49.         public Builder setNegativeButton(int negativeButtonTextId,  
  50.                 OnClickListener listener) {  
  51.             mNegativeButtonText = (String) mContext  
  52.                     .getText(negativeButtonTextId);  
  53.             mNegativeButtonClickListener = listener;  
  54.             return this;  
  55.         }  
  56.   
  57.         public Builder setNegativeButton(String negativeButtonText,  
  58.                 OnClickListener listener) {  
  59.             mNegativeButtonText = negativeButtonText;  
  60.             mNegativeButtonClickListener = listener;  
  61.             return this;  
  62.         }  
  63.   
  64.         public CustomAlertDialog create() {  
  65.             LayoutInflater inflater = LayoutInflater.from(mContext);  
  66.             View view = inflater.inflate(R.layout.custom_alert_dialog, null);  
  67.             final CustomAlertDialog customAlertDialog = new CustomAlertDialog(  
  68.                     mContext, R.style.CustomAlertDialog);  
  69.             customAlertDialog.addContentView(view, new ViewGroup.LayoutParams(  
  70.                     ViewGroup.LayoutParams.MATCH_PARENT,  
  71.                     ViewGroup.LayoutParams.WRAP_CONTENT));  
  72.             TextView tvAlertTitle = (TextView) view  
  73.                     .findViewById(R.id.tvAlertDialogTitle);  
  74.             tvAlertTitle.setText(mTitle);  
  75.   
  76.             if (!TextUtils.isEmpty(mMessage)) {  
  77.                 TextView tvAlertDialogMessage = (TextView) view  
  78.                         .findViewById(R.id.tvAlertDialogMessage);  
  79.                 tvAlertDialogMessage.setText(mMessage);               
  80.                 View vMessageLine = (View)view.findViewById(R.id.vMessageLine);  
  81.                 vMessageLine.setVisibility(View.VISIBLE);  
  82.             }  
  83.   
  84.             Button btnPositive = (Button) view  
  85.                     .findViewById(R.id.btnAlertDialogPositive);  
  86.             if (!TextUtils.isEmpty(mPositiveButtonText)) {  
  87.                 btnPositive.setText(mPositiveButtonText);  
  88.                 if (mPositiveButtonClickListener != null) {  
  89.                     btnPositive.setOnClickListener(new View.OnClickListener() {  
  90.                         @Override  
  91.                         public void onClick(View v) {  
  92.                             mPositiveButtonClickListener.onClick(  
  93.                                     customAlertDialog, BUTTON_POSITIVE);  
  94.                         }  
  95.                     });  
  96.                 }  
  97.             } else {  
  98.                 btnPositive.setVisibility(View.GONE);  
  99.             }  
  100.             Button btnNegative = (Button) view  
  101.                     .findViewById(R.id.btnAlertDialogNegative);  
  102.             if (!TextUtils.isEmpty(mNegativeButtonText)) {  
  103.                 btnNegative.setText(mNegativeButtonText);  
  104.                 if (mNegativeButtonClickListener != null) {  
  105.                     btnNegative.setOnClickListener(new View.OnClickListener() {  
  106.                         @Override  
  107.                         public void onClick(View v) {  
  108.                             mNegativeButtonClickListener.onClick(  
  109.                                     customAlertDialog, BUTTON_NEGATIVE);  
  110.                         }  
  111.                     });  
  112.                 }else{  
  113.                     btnNegative.setOnClickListener(new View.OnClickListener() {  
  114.                         @Override  
  115.                         public void onClick(View v) {  
  116.                             customAlertDialog.dismiss();  
  117.                         }  
  118.                     });  
  119.                 }  
  120.             } else {  
  121.                 btnNegative.setVisibility(View.GONE);  
  122.             }  
  123.             if (View.VISIBLE == btnPositive.getVisibility()  
  124.                     && View.GONE == btnNegative.getVisibility()) {  
  125.                 RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) btnPositive  
  126.                         .getLayoutParams();               
  127.                 layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;     
  128.                 btnPositive.setLayoutParams(layoutParams);  
  129.             }  
  130.             return customAlertDialog;  
  131.         }  
  132.   
  133.         public CustomAlertDialog show() {  
  134.             CustomAlertDialog dialog = create();  
  135.             dialog.show();  
  136.             return dialog;  
  137.         }  

在上面,可以看到 setTitle,setMessage,setPositiveButton和setNegativeButton等都会有两个实现,其中一个是接收资源id,一个是直接接收字符串。

后面的就是 create 方法,在这里,

a)会利用LayoutInflater将我们最前面定义的布局文件给解析出来,设置给View变量,

b)同时,我们会利用前面定义的带themeId的构造函数,创建一个CustomAlertDialog对象,并将布局给加载到对话框上面。

c)将 Title,Message和 PositiveButton,NegativeButton等对应控件的内容给初始化,当然,需要根据参数值的判断,当我们在创建这个对话框的时候,有赋值的话,对需要去初始化,比如,Title 是必须的,而Message就不是必须的,同样,NegativeButton也不是必须的,所以需要根据其实际逻辑去判断要不要展现。

d)因为在定义布局的时候,是定义了两个按钮的,它们是一样大的,左右并排,那么如果只有一个按钮的话,就需要将其居中放置(其实在这里,我没有实现不改变大小,居中放置,所以只是将显示的按钮整个变大,居中放置,还没想明白为什么不行)。

e)最后定义一个show方法,将对话框给显示出来。

f)在Builder定义了两个 DialogInterface.OnClickListener,当点击我们布局的按钮的时候,会在按钮的View.OnClickListener方法中去调用DialogInterface.OnClickListener的onClick方法,而我们在Activity中创建AlertDialog的时候会去实现这个接口的方法。

2.3)在Activity中创建CustomAlertDialog,其实跟创建普通的AlertDialog方法一样,因为我们都是照着它的方法来实现的,只是去掉了一些我们不需要的方法,代码如下:

  1. new CustomAlertDialog.Builder(context)  
  2.     .setTitle(title)  
  3.     .setNegativeButton(context.getString(R.string.dialog_no), null)  
  4.     .setPositiveButton(context.getString(R.string.dialog_yes), listener)  
  5.     .show();  

上一篇:建筑施工安全技术交底范本1000例 下一篇:C#清除一个事件的所有委托