Java / 对话框:AlertDialog

对话框:AlertDialog

前两节我们讲到了 Toast 和 Notification,这两个属于单向的通知,也就是说只能由我们给用户传递信息,而不能接收用户的选择。当你希望在 Acitivity 内给用户传递信息的同时给用户一些选择权,并且不希望切换屏幕页面的时候,AlertDialog 将是最佳的选择。

1. AlertDialog 的特性

对话框是一个可以用来展示提示信息并支持用户输入的小弹窗

AlertDialog 可以用来让用户提交问题、做选择、确定/取消操作、向用户发送通知、错误等信息。它可以帮助我们在不跳转 Activity 的情况下轻松弹出一个悬浮窗,在本节课程中,我们会讨论如何创建各种各样常见的对话框。

2. AlertDialog 的常用 API

AlertDialog 在使用中主要以 API 为主,常用方法如下:

  • setIcon(Drawable icon):
    设置Alert Dialog窗口的icon
  • setCancelable(boolean cancel able):
    设置是否支持取消(取消通常是指点窗口外或者点“Back”)
  • setTitle(CharSequence title):
    设置对话框上的标题
  • setMessage(CharSequence message):
    设置对话框上的提示信息
  • setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, DialogInterface.OnMultiChoiceClickListener listener):
    在对话框上添加多选列表,参数描述:
    • items:多选项文本数组
    • checkedItems:默认状态,true表示默认选中;false默认取消
    • listener:用户选择监听器
  • setOnCancelListener(DialogInterface.OnCancelListener onCancelListener):
    设置关闭监听器,在用户关闭的时候回调此接口
  • setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener):
    设置确定监听器,在用户点击确定的时候回调此接口
  • setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener):
    设置取消监听器,在用户选择“取消”、“否定”等时候毁掉此接口

3. AlertDialog 的使用方法

AlertDialog 的用法和上一节的 Notification 类似,系统也提供了 Builder 建造者,通过 Builder 的create()方法可以创建对话框,然后通过show()方法展示,如下:

AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();

3.1 使用步骤

Step 1: 创建AlertDialog.Builder对象
我们也可以直接创建 AlertDialog,但这样不方便我们自定义一些功能及样式,所以更多时候还是会采用构建者模式中的 Builder 对象帮助我们去构建我们需要的 AlertDialog。

Step 2: 设置对话框的内容样式
这里主要涉及到图标icon、标题以及提示内容四个部分,对应以下 3 个接口:

  • setIcon
  • setTitle
  • setMessage

这几个是几乎所有对话框都会用到的方法,对于一些特殊样式的 AlertDialog 还会有一些特殊接口,具体的方法我们会在下一个小节看到。

Step 3: 设置按钮
分别调用setPositiveButton()setNegativeButton()setNeutralButton()来设置“确定”、“取消”、“中立”按钮的显示文本及点击事件回调

Step 4: 创建 AlertDialog对象并展示
在设置完对话框的样式之后,我们直接调用 Builder 的create()方法创建 AlertDialog 实例,最后调用 show()方法将对话框显示出来。

3.2 普通对话框

一个普通的 AlertDialog 也是大家日常见到最多的一种,直接弹出一个提示,然后给出 1 - 3 个选项,比如“是”、“否”、“取消”等等,使用方法非常简单,基本上可以直接套用 3.1小节的步骤,代码如下:

package com.emercy.myapplication;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.alert).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		AlertDialog alertDialog = builder
				.setIcon(R.drawable.warning)
				.setTitle("系统消息:")
				.setMessage("弹出一个普通的AlertDialog,\n提供确定、退出、取消三个Button")
				.setPositiveButton("确定", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Toast.makeText(MainActivity.this, "已确定", Toast.LENGTH_SHORT).show();
					}
				})
				.setNegativeButton("取消", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Toast.makeText(MainActivity.this, "已为您取消", Toast.LENGTH_SHORT).show();
					}
				}).setNeutralButton("退出", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Toast.makeText(MainActivity.this, "已退出对话框", Toast.LENGTH_SHORT).show();
					}
				}).create();             // 通过 create() 创建AlertDialog对象
		alertDialog.show();     		 // 通过 show() 展示对话框
	}
}

然后为 Activity 编写一个布局文件,其中放置一个 Button 用于触发对话框,如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="MainActivity">
      
   <Button
      android:layout_centerInParent="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="弹出普通 AlertDialog"
      android:id="@+id/alert" />
</RelativeLayout>

编译之后点击屏幕中间的 Button,弹出来的就是一个普通对话框了。我们设置了“确定”、“取消”、“中立” 3 个Button,分别表示“确定”、“取消”以及“退出对话框” 3 种操作,实际使用中,可以在回调接口里针对 3 种 Button 设置不同的回调逻辑,效果如下:

普通AlertDialog

3.3 单选对话框

单选对话框在普通对话框的基础之上增加一个用户的输入,顾名思义,我们可以给用户提供一些选项让用户勾选,然后在点击“确定”之后获取到用户的选择。
通过setSingleChoiceItems方法设置一个字符串数组作为单选项,然后通过DialogInterface.OnClickListener接口监听用户的选择操作。

package com.emercy.myapplication;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	final String[] hero_road = new String[] { "对抗路", "打野", "中路", "发育路", "辅助" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.alert).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		AlertDialog alert = builder
				.setIcon(R.drawable.warning)
				.setTitle("选择你要走的峡谷分路")
				.setSingleChoiceItems(hero_road, 0,
						new DialogInterface.OnClickListener()  {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								Toast.makeText(getApplicationContext(),"我要玩" + hero_road[which], Toast.LENGTH_SHORT).show();
							}
						}).create();
		alert.show();
	}
}

效果如下:

单选对话框

3.4 多选对话框

布局文件保持不变,只需要修改点击事件即可。通过setMultiChoiceItems()接口设置一个多选列表,在用户选择的时候系统会回调onClick()方法,在其中可以记录下用户的选择,代码如下:

package com.emercy.myapplication;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	final String[] hero_road = new String[] { "对抗路", "打野", "中路", "发育路", "辅助" };
	private boolean[] checked = new boolean[hero_road.length];
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.alert).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		 AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        AlertDialog alert = builder
	                .setIcon(R.drawable.warning)
	                .setTitle("选择你擅长的峡谷分路")
	                .setMultiChoiceItems(hero_road, null, new DialogInterface.OnMultiChoiceClickListener() {
						
						@Override
						public void onClick(DialogInterface dialog, int which, boolean isChecked) {
							checked[which] = isChecked;		
						}
					}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							StringBuilder stringBuilder = new StringBuilder();
							stringBuilder.append("“");
							for (int i = 0; i < hero_road.length; i++) {
								if (checked[i]) {
									stringBuilder.append(hero_road[i]);
									stringBuilder.append(",");
								}
							}
							stringBuilder.deleteCharAt(stringBuilder.length() - 1);
							stringBuilder.append("”");
							Toast.makeText(MainActivity.this, "我擅长" + stringBuilder, Toast.LENGTH_SHORT).show();
						}
					}).create();
	        alert.show();
	}
}

效果如下:

多选对话框

3.5 列表对话框

使用列表对话框会弹出一个选择列表,用户可以从列表中选择一个并直接关闭对话框,设置列表采用setItems()接口:

package com.emercy.myapplication;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	final String[] hero_road = new String[] { "对抗路", "打野", "中路", "发育路", "辅助" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.alert).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		 AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        AlertDialog alert = builder
	                .setIcon(R.drawable.warning)
	                .setTitle("选择你要走的峡谷分路")
	                .setItems(hero_road, new DialogInterface.OnClickListener() {
	                    
	                    @Override
	                    public void onClick(DialogInterface dialog, int which) {
	                        Toast.makeText(getApplicationContext(),"我要走" + hero_road[which], Toast.LENGTH_SHORT).show();    
	                    }
	                }).create();
	        alert.show();
	}
}

效果如图:

列表对话框

4. 小结

AlertDialog 相比前两节学到的 Toast 和 Notification 而言,它会直接挡住用户的界面,等待用户主动关闭,是一个比较强的通知方式。因此在使用的时候一定要慎重,不要使用的太频繁而对用户造成过度的打扰。AlertDialog 不但可以给用户通知,还能轻易的接收用户的选择,互动性比较强。它的创建方法通常是采用构建者模式,通过 AlertDialog.Builder 类来定制它的样式及内容,根据样式的不同常用的有“普通对话框”、“单选对话框”、“多选对话框”以及“列表对话框”,在设置完成之后通过create()创建 AlertDialog,最终通过show()完成展示。这种通过 Builder 来构建的方式在 Android 中非常常用,你学会了吗?