Android学习小Demo(15)一个自定义AlertDialog的实现

在Android的应用中,很多时候,都会利用到 AlertDialog 来弹出信息,或者让用户进行选择,或者告知用户某些信息,而系统自带的背景效果,一般不能够满足需求,所以很多时候,就会存在自定义 AlertDialog 的需求。其实不仅是AlertDialog,为了完善一款应用,很多控件都需要自定义,比如前面文章中提到过的EditText 等。

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

Android学习小Demo(15)一个自定义AlertDialog的实现

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

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/shape_alert_dialog"
    android:minWidth="280dp"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvAlertDialogTitle"
        android:textSize="20sp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:textColor="#FFFFFF"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:gravity="center" />

    <View
        android:id="@+id/vTitleLine"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@drawable/line_divider" >
    </View>

    <TextView
        android:id="@+id/tvAlertDialogMessage"
        android:layout_width="match_parent"
        android:textSize="16sp"
        android:layout_height="50dp"        
        android:visibility="gone" />

    <View
        android:id="@+id/vMessageLine"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@drawable/line_divider"
        android:visibility="gone" >
    </View>

    <RelativeLayout
        android:id="@+id/rlAlertDialogButtons"
        android:layout_width="270dp"
        android:layout_marginBottom="10dp"
        android:layout_height="50dp"
        android:layout_gravity="center" >

        <Button
            android:id="@+id/btnAlertDialogNegative"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_margin="5dp"
            android:textColor="#FFFFFF"
            android:background="@drawable/shape_alert_button"
            android:gravity="center" />

        <Button
            android:id="@+id/btnAlertDialogPositive"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_margin="5dp"
            android:textColor="#FFFFFF"
            android:background="@drawable/shape_alert_button"
            android:gravity="center" />
    </RelativeLayout>

</LinearLayout>

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

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

2.1)首先是构造函数:

public class CustomAlertDialog extends Dialog {
	

	public CustomAlertDialog(Context context) {
		super(context);
	}

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

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

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

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

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

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

public static class Builder {
		
		private Context mContext;
		private String mTitle, mMessage;
		private String mPositiveButtonText, mNegativeButtonText;

		private OnClickListener mPositiveButtonClickListener,
				mNegativeButtonClickListener;

		public Builder(Context context) {
			mContext = context;
		}

		public Builder setTitle(int resId) {
			mTitle = (String) mContext.getText(resId);
			return this;
		}

		public Builder setTitle(String title) {
			mTitle = title;
			return this;
		}

		public Builder setMessage(int resId) {
			mMessage = (String) mContext.getText(resId);
			return this;
		}

		public Builder setMessage(String message) {
			mMessage = message;
			return this;
		}

		public Builder setPositiveButton(int positiveButtonTextId,
				OnClickListener listener) {
			mPositiveButtonText = (String) mContext
					.getText(positiveButtonTextId);
			mPositiveButtonClickListener = listener;
			return this;
		}

		public Builder setPositiveButton(String positiveButtonText,
				OnClickListener listener) {
			mPositiveButtonText = positiveButtonText;
			mPositiveButtonClickListener = listener;
			return this;
		}

		public Builder setNegativeButton(int negativeButtonTextId,
				OnClickListener listener) {
			mNegativeButtonText = (String) mContext
					.getText(negativeButtonTextId);
			mNegativeButtonClickListener = listener;
			return this;
		}

		public Builder setNegativeButton(String negativeButtonText,
				OnClickListener listener) {
			mNegativeButtonText = negativeButtonText;
			mNegativeButtonClickListener = listener;
			return this;
		}

		public CustomAlertDialog create() {
			LayoutInflater inflater = LayoutInflater.from(mContext);
			View view = inflater.inflate(R.layout.custom_alert_dialog, null);
			final CustomAlertDialog customAlertDialog = new CustomAlertDialog(
					mContext, R.style.CustomAlertDialog);
			customAlertDialog.addContentView(view, new ViewGroup.LayoutParams(
					ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT));
			TextView tvAlertTitle = (TextView) view
					.findViewById(R.id.tvAlertDialogTitle);
			tvAlertTitle.setText(mTitle);

			if (!TextUtils.isEmpty(mMessage)) {
				TextView tvAlertDialogMessage = (TextView) view
						.findViewById(R.id.tvAlertDialogMessage);
				tvAlertDialogMessage.setText(mMessage);				
				View vMessageLine = (View)view.findViewById(R.id.vMessageLine);
				vMessageLine.setVisibility(View.VISIBLE);
			}

			Button btnPositive = (Button) view
					.findViewById(R.id.btnAlertDialogPositive);
			if (!TextUtils.isEmpty(mPositiveButtonText)) {
				btnPositive.setText(mPositiveButtonText);
				if (mPositiveButtonClickListener != null) {
					btnPositive.setOnClickListener(new View.OnClickListener() {
						@Override
						public void onClick(View v) {
							mPositiveButtonClickListener.onClick(
									customAlertDialog, BUTTON_POSITIVE);
						}
					});
				}
			} else {
				btnPositive.setVisibility(View.GONE);
			}
			Button btnNegative = (Button) view
					.findViewById(R.id.btnAlertDialogNegative);
			if (!TextUtils.isEmpty(mNegativeButtonText)) {
				btnNegative.setText(mNegativeButtonText);
				if (mNegativeButtonClickListener != null) {
					btnNegative.setOnClickListener(new View.OnClickListener() {
						@Override
						public void onClick(View v) {
							mNegativeButtonClickListener.onClick(
									customAlertDialog, BUTTON_NEGATIVE);
						}
					});
				}else{
					btnNegative.setOnClickListener(new View.OnClickListener() {
						@Override
						public void onClick(View v) {
							customAlertDialog.dismiss();
						}
					});
				}
			} else {
				btnNegative.setVisibility(View.GONE);
			}
			if (View.VISIBLE == btnPositive.getVisibility()
					&& View.GONE == btnNegative.getVisibility()) {
				RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) btnPositive
						.getLayoutParams();				
				layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;	
				btnPositive.setLayoutParams(layoutParams);
			}
			return customAlertDialog;
		}

		public CustomAlertDialog show() {
			CustomAlertDialog dialog = create();
			dialog.show();
			return dialog;
		}

在上面,可以看到 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方法一样,因为我们都是照着它的方法来实现的,只是去掉了一些我们不需要的方法,代码如下:

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

嗯,到这里,我们的自定义AlertDialog就实现了。


Android学习小Demo(15)一个自定义AlertDialog的实现,布布扣,bubuko.com

Android学习小Demo(15)一个自定义AlertDialog的实现

上一篇:android之数据存储之SQLite


下一篇:Android 获取信号强度